package com.manning.aip.portfolio;

import java.util.ArrayList;

import android.app.ListActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.manning.aip.portfolio.service.IStockService;

/**
 * Główna aktywność aplikacji. Udostępnia prosty formularz do wprowadzania
 * danych o akcjach, które użytkownik chce śledzi, a także wyświetla listę 
 * obserwowanych akcji. Aktywność korzysta z usługi 
 * {@link com.manning.aip.portfolio.PortfolioManagerService PortfolioManagerService}
 * do pobierania portfela akcji i ich dodawania.
 * 
 * @author Michael Galpin
 *
 */
public class ViewStocks extends ListActivity {

	private static final String LOGGING_TAG = "ViewStocks";
	
	// Lista akcji wyświetlanych użytkownikowi.
	private ArrayList<Stock> stocks;
	// Usługa używana do utrwalania i pobierania akcji.
	private IStockService stockService;
	// Czy usługa jest obecnie podłączona?
	private boolean bound = false;
	
	// Połączenie z usługą i kod do obsługi zdarzeń związanych z cyklem życia usługi.
	private ServiceConnection connection = new ServiceConnection(){

		public void onServiceConnected(ComponentName className, 
				IBinder service) {
			stockService = IStockService.Stub.asInterface(service);
			Log.d(LOGGING_TAG,"Podłączono usługę");
			try {
				stocks = (ArrayList<Stock>) stockService.getPortfolio();
				if (stocks == null){
					stocks = new ArrayList<Stock>(0);
					Log.d(LOGGING_TAG, "Usługa nie zwróciłą akcji");
				} else {
					Log.d(LOGGING_TAG, "Pobrano "+ stocks.size() +" akcji z usługi");
				}
				refresh();
			} catch (RemoteException e) {
				Log.e(LOGGING_TAG, "Wyjątek przy pobieraniu portfela akcji z usługi",e);
			}
		}

		public void onServiceDisconnected(ComponentName className) {
			stockService = null;
			Log.d(LOGGING_TAG,"Zerwano połączenie z usługą");
		}
		
	};
	
	@Override
	public void onStart(){
		super.onStart();
        // Tworzenie wyjściowej listy.
		if (!bound){
			bound = bindService(
					new Intent(ViewStocks.this, PortfolioManagerService.class), 
					connection, Context.BIND_AUTO_CREATE);
			Log.d(LOGGING_TAG, "Podłączono usługę: " + bound);
		}
		if (!bound){
			Log.e(LOGGING_TAG, "Nieudane podłączenie usługi");
			throw new RuntimeException("Nieudane wyszukiwanie usługi");
		}
		setListAdapter(new BaseAdapter(){

			public int getCount() {
				if (stocks == null){
					return 0;
				}
				return stocks.size();
			}

			public Object getItem(int position) {
				if (stocks == null){
					return null;
				}
				return stocks.get(position);
			}

			public long getItemId(int position) {
				if (stocks == null){
					return 0L;
				}
				return stocks.get(position).getId();
			}

			public View getView(int position, View convertView, 
					ViewGroup parent) {
				if (convertView == null){
					LayoutInflater inflater = getLayoutInflater();
					convertView = 
						inflater.inflate(R.layout.stock, parent, false);
				}
				TextView rowTxt = 
					(TextView) convertView.findViewById(R.id.rowTxt);
				rowTxt.setText(stocks.get(position).toString());
				return convertView;
			}

			@Override
			public boolean hasStableIds() {
				return true;
			}
        	
        });
	}
	
	@Override
	public void onPause(){
		super.onPause();
		if (bound){
			bound = false;
			unbindService(connection);
		}
	}
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
    	// Tworzenie elementów interfejsu użytkownika.
    	// Dane zostały wczytane w metodzie <code>onStart</code>.
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);    

        // Dodawanie kontrolek.
        final EditText symbolIn = (EditText) findViewById(R.id.inputSymbol);
        final EditText maxIn = (EditText) findViewById(R.id.inputMax);
        final EditText minIn = (EditText) findViewById(R.id.inputMin);
        final EditText priceIn = (EditText) findViewById(R.id.inputPrice);
        final EditText quantIn = (EditText) findViewById(R.id.inputQuant);
        
        // Dodawanie procedury obsługi kliknięcia przycisku.
		Button button = (Button) findViewById(R.id.btn);
		button.setOnClickListener(new OnClickListener(){
			public void onClick(View v) {
				String symbol = symbolIn.getText().toString();
				symbolIn.setText("");
				double max = Double.parseDouble(maxIn.getText().toString());
				maxIn.setText("");
				double min = Double.parseDouble(minIn.getText().toString());
				minIn.setText("");
				double pricePaid = 
					Double.parseDouble(priceIn.getText().toString());
				priceIn.setText("");
				int quantity = Integer.parseInt(quantIn.getText().toString());
				quantIn.setText("");
				Stock stock = new Stock(symbol, pricePaid, quantity);
				stock.setMaxPrice(max);
				stock.setMinPrice(min);
				// Dodawanie akcji do portfela za pomocą działającej w tle usługi.
				new AsyncTask<Stock,Void,Stock>(){
					@Override
					protected Stock doInBackground(Stock... newStocks) {						
						try {
							return stockService.addToPortfolio(newStocks[0]);
						} catch (RemoteException e) {
							Log.e(LOGGING_TAG, "Wyjątek w czasie dodawania " +
									"akcji do portfela", e);
						}
						return null;
					}
					@Override
					protected void onPostExecute(Stock s){
						Log.d(LOGGING_TAG, "Akcje zwrócone przez usługę: " + s);
						if (s == null){
							Log.w(LOGGING_TAG, "Usługa zwróciła null " +
									"lub nieprawidłowe dane");
							Toast.makeText(ViewStocks.this, "Akcji nie znaleziono", 
									Toast.LENGTH_SHORT);
						} else { 
							refreshStockData();
						}
					}
				}.execute(stock);
			}
		});
    }

	@Override
	protected void onDestroy() {
		super.onDestroy();
		// Zerwanie połączenia z usługą.
		unbindService(connection);
	}

    // Aktualizowanie danych o akcjach otrzymanych od usługi
	// i odświeżanie interfejsu użytkownika.
	private void refreshStockData() {
		if (stocks != null && stocks.size() > 0){
			new AsyncTask<Void, Void, ArrayList<Stock>>(){
				@Override
				protected void onPostExecute(ArrayList<Stock> result) {
					Log.d(LOGGING_TAG, "Otrzymano nowe dane z usługi");
					if (result != null){
						stocks = result;
						refresh();
					} else {
						Toast.makeText(ViewStocks.this, "Wyjątek przy pobieraniu " +
								"najnowszych danych o akcjach", Toast.LENGTH_SHORT);
					}
				}
	
				@Override
				protected ArrayList<Stock> doInBackground(Void... nada){
					try {
						return (ArrayList<Stock>) stockService.getPortfolio();
					} catch (Exception e) {
						Log.e(LOGGING_TAG, "Wyjątek przy pobieraniu danych o akcjach", e);
					}
					return null;
				}
	    	}.execute();
		}
	}
    
    private void refresh(){
    	Log.d(LOGGING_TAG, "Odświeżanie interfejsu użytkownika na podstawie nowych danych");
		for (Stock s : stocks){
			Log.d(LOGGING_TAG, "Otrzymano dane o akcjach: " + s.toString());
		}
    	BaseAdapter adapter = (BaseAdapter) this.getListAdapter();
    	adapter.notifyDataSetChanged();
    }
}