package com.ethostream.ethoandroid;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;

import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

public class PropContacts extends ListActivity
{
	private static final String REMOTE_QUERY_SITE = "http://android.telkonet.com/dbpropcontacts.php";
	
	private static final String PROPCONTACTS_CONTACTID = "ContactID";
	private static final String PROPCONTACTS_PARENTID = "ParentID";
	private static final String PROPCONTACTS_PARENT_TYPE = "ParentType";
	private static final String PROPCONTACTS_NAME = "ContactName";
	private static final String PROPCONTACTS_ROLE = "ContactRole";
	private static final String PROPCONTACTS_PHONE = "ContactPhone";
	private static final String PROPCONTACTS_EXT = "ContactExten";
	private static final String PROPCONTACTS_FAX = "ContactFax";
	private static final String PROPCONTACTS_EMAIL = "ContactEmail";
	private static final String PROPCONTACTS_CELL = "ContactCell";
	private static final String PROPCONTACTS_NOTE = "ContactNote";
	private static final String PROPCONTACTS_GROUP = "GroupName";
	
	private int propID = 0;
	private RowAdapter rowAdapter;
	
	private static final int ACTIVITY_CONTACT = 0; 
	
	private Context context;
	
	@Override
	public void onCreate(Bundle savedInstanceState) 
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.propcontacts);
		context = this;
		
		Bundle bundle = getIntent().getExtras();
		propID = Integer.parseInt(bundle.getString("ID"));
		if (propID < 1)
		{
			Log.e(this.toString(), "Invalid ID, quitting.");
			setResult(RESULT_CANCELED);
			finish();
		}
		
		ArrayList<ContentValues> contacts = new ArrayList<ContentValues>();
		DownloadThread dlt = new DownloadThread();
		dlt.execute();
		try
		{
			//TODO: timeout and message
			contacts = dlt.get();
		} catch (InterruptedException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		rowAdapter = new RowAdapter(this, R.layout.propcontacts_item, contacts);
		setListAdapter(rowAdapter);

		ListView lv = getListView();
		lv.setTextFilterEnabled(true);
		lv.setOnItemClickListener(new OnItemClickListener() 
		{
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
			{
				// When clicked, do something
				switchView(ACTIVITY_CONTACT, "CONTACT", ((ContentValues) parent.getAdapter().getItem(position)).getAsString(PROPCONTACTS_CONTACTID));

			}
		});
	}
	
	private class DownloadThread extends AsyncTask<Void, Void, ArrayList<ContentValues>> 
	{
		final ProgressDialog dialog = new ProgressDialog(context);
		@Override
		protected void onPreExecute()
		{
			dialog.setTitle(R.string.activity_loading_label);
			dialog.setMessage(context.getString(R.string.activity_loading_message));
			dialog.show();
		}
		@Override
		protected ArrayList<ContentValues> doInBackground(Void... params) 
		{
			ArrayList<ContentValues> contacts = new ArrayList<ContentValues>();
			contacts.addAll(0, getRemotePropertyInfo(true));
			contacts.addAll(contacts.size(), getRemotePropertyInfo(false));
			return contacts;

		}
		@Override
		protected void onPostExecute(ArrayList<ContentValues> retValue) 
		{
			dialog.dismiss();
		}
	 }
	
	private ArrayList<ContentValues> getRemotePropertyInfo(boolean group)
	{
		InputStream is = null;
		ArrayList<ContentValues> list = new ArrayList<ContentValues>();
		ArrayList<NameValuePair> queryResult = new ArrayList<NameValuePair>();
		StringBuilder sb = null;
		String result;
		
		//httpPost
		try{
			HttpClient httpclient = new DefaultHttpClient();
			HttpPost httppost = new HttpPost(REMOTE_QUERY_SITE + "?ID=" + Integer.toString(propID) + "&GROUP=" + group);
			httppost.setEntity(new UrlEncodedFormEntity(queryResult));
			HttpResponse response = httpclient.execute(httppost);
			HttpEntity entity = response.getEntity();
			is = entity.getContent();
		}catch(Exception e){
			Log.e(this.toString(), "Error in http connection"+e.toString());
			return new ArrayList<ContentValues>(0);
		}
		//convertString
		try{
			BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
			sb = new StringBuilder();
			sb.append(reader.readLine() + "\n");
			String line="0";
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
			is.close();
			result=sb.toString();
		}catch(Exception e){
			Log.e("log_tag", "Error converting result "+e.toString());
			return new ArrayList<ContentValues>(0);
		}
		//parseJSON
		try
		{
			JSONArray jArray = new JSONArray(result);
			JSONObject json_data=null;
			for (int i = 0; i < jArray.length(); i++)
			{
				json_data = jArray.getJSONObject(i);
				ContentValues cv = new ContentValues();
				cv.put(PROPCONTACTS_CONTACTID, json_data.getString(PROPCONTACTS_CONTACTID));
				cv.put(PROPCONTACTS_PARENTID, json_data.getString(PROPCONTACTS_PARENTID));
				cv.put(PROPCONTACTS_PARENT_TYPE, json_data.getString(PROPCONTACTS_PARENT_TYPE));
				cv.put(PROPCONTACTS_NAME, json_data.getString(PROPCONTACTS_NAME));
				cv.put(PROPCONTACTS_ROLE, json_data.getString(PROPCONTACTS_ROLE));
				cv.put(PROPCONTACTS_PHONE, json_data.getString(PROPCONTACTS_PHONE));
				cv.put(PROPCONTACTS_EXT, json_data.getString(PROPCONTACTS_EXT));
				cv.put(PROPCONTACTS_FAX, json_data.getString(PROPCONTACTS_FAX));
				cv.put(PROPCONTACTS_EMAIL, json_data.getString(PROPCONTACTS_EMAIL));
				cv.put(PROPCONTACTS_CELL, json_data.getString(PROPCONTACTS_CELL));
				cv.put(PROPCONTACTS_NOTE, json_data.getString(PROPCONTACTS_NOTE));
				if (group)
				{
					cv.put(PROPCONTACTS_GROUP, json_data.getString(PROPCONTACTS_GROUP));
				}
				list.add(cv);
			}
		}
		catch(Exception e)
		{
			Log.e(this.toString(), "FAILURE TO ACQUIRE REMOTE PROP INFO");
			return new ArrayList<ContentValues>(0);
		}
		return list;
	}
	
	private void switchView(int ACTIVITY, String key, String value)
    {
    	switch(ACTIVITY)
    	{
    		case ACTIVITY_CONTACT:
    		{
            	Intent i = new Intent(this, Contact.class);
            	i.putExtra(key, value);
            	startActivityForResult(i, ACTIVITY_CONTACT);
            	break;
    		}
    		default:
    		{
    			break;
    		}
    	}
    }
	
	private class RowAdapter extends ArrayAdapter<ContentValues> implements Filterable
	{
		private ArrayList<ContentValues> list;
		private ArrayList<ContentValues> originalList;
		private Filter filter;
		int filterSize = 0;
		
		public RowAdapter(Context context, int textViewResourceId, ArrayList<ContentValues> noteList) 
        {
                super(context, textViewResourceId, noteList);
                list = noteList;
                originalList = list;
        }
		
		@Override
        public int getCount() 
        {
            return list.size();
        }
		
		@Override
        public View getView(int position, View convertView, ViewGroup parent) 
        {
        	View v = convertView;
        	if (v == null) 
        	{
        		LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        		v = vi.inflate(R.layout.propcontacts_item, parent, false);
        	}
        	
        	ContentValues cv = list.get(position);
        	TextView group = (TextView) v.findViewById(R.id.propcontacts_group);
        	TextView name = (TextView) v.findViewById(R.id.propcontacts_name);
        	TextView role = (TextView) v.findViewById(R.id.propcontacts_role);
        	
        	//TODO: There is a bug where after filtering takes place the styling for group contacts goes away
        	if (cv.getAsString(PROPCONTACTS_GROUP) == null)
        	{
        		v.getContext();
        		group.setVisibility(android.view.View.GONE);
        	}
        	else
        	{
        		v.getContext();
        		group.setVisibility(android.view.View.VISIBLE);
        		group.setText(cv.getAsString(PROPCONTACTS_GROUP));
        	}
        	if (cv.getAsString(PROPCONTACTS_NAME) != null)
        	{
        		name.setText(cv.getAsString(PROPCONTACTS_NAME));
        	}
        	if (cv.getAsString(PROPCONTACTS_ROLE) != null)
        	{
        		role.setText(cv.getAsString(PROPCONTACTS_ROLE));
        	}
       	
        	return v;
        }
		
		public Filter getFilter()
        {
        	if (filter == null)
        	{
        		filter = new APFilter();
        	}
        	return filter;
        }
		private class APFilter extends Filter
	    {

			@Override
			protected FilterResults performFiltering(CharSequence constraint)
			{
				final ArrayList<ContentValues> constraintList = new ArrayList<ContentValues>(list.size());
				FilterResults results = new FilterResults();
				if (list == null)
				{
					list = originalList;
					results.values = list;
					results.count = list.size();
					return results;
				}
				if ( filterSize >= constraint.length())
				{
					// Previous constraint was more defined, we're reducing the filter so we need to refresh the list
					// Also need to refresh if filter is the same size, since that probably means we've unchecked showRed box
					Log.i(this.toString(), "Refreshing list for reduced filter");
					list = originalList;
				}
				// Start Filtering
				String constraintString = constraint.toString().toLowerCase();
				Log.i(this.toString(), "START FILTER===========================================================");
				Log.i(this.toString(), "Filtering over a list of -- "+list.size()+" -- elements...");
				int size = list.size();
				for (int i = 0; i < size; i++)
				{
					if (list.get(i).getAsString(PROPCONTACTS_NAME).toLowerCase().contains(constraintString) ||
							list.get(i).getAsString(PROPCONTACTS_ROLE).toLowerCase().contains(constraintString) ||
							(list.get(i).getAsString(PROPCONTACTS_GROUP) != null && list.get(i).getAsString(PROPCONTACTS_GROUP).toLowerCase().contains(constraintString)))
					{
						constraintList.add(list.get(i));
					}
				}
				Log.i(this.toString(), "END FILTER===========================================================");
				filterSize = constraint.length();
				results.values = constraintList;
				results.count = constraintList.size();
				return results;
			}

			@SuppressWarnings("unchecked")
			@Override
			protected void publishResults(CharSequence constraint,
					FilterResults results)
			{
				// TODO SuppressWarnings
				list = (ArrayList<ContentValues>) results.values;
				if (results.count > 0) {
	                notifyDataSetChanged();
	            } else {
	                notifyDataSetInvalidated();
	            }
			}
	    	
	    }
	}
    
}