/* 
 * Copyright 2012 by AVM GmbH <info@avm.de>
 *
 * This software contains free software; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License ("License") as 
 * published by the Free Software Foundation  (version 3 of the License). 
 * This software is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the copy of the 
 * License you received along with this software for more details.
 */

package de.avm.android.fritzapp.gui;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.AsyncQueryHandler;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnKeyListener;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ResourceCursorAdapter;
import android.widget.TextView;
import de.avm.android.fritzapp.R;
import de.avm.android.fritzapp.com.ComSettingsChecker;
import de.avm.android.fritzapp.com.DataHub;
import de.avm.android.fritzapp.service.BoxServiceConnection;
import de.avm.android.fritzapp.service.IBoxService;
import de.avm.android.fritzapp.util.LocalContacts;
import de.avm.android.fritzapp.util.ResourceHelper;
import de.avm.android.tr064.Tr064Capabilities;
import de.avm.android.tr064.exceptions.SslErrorException;
import de.avm.android.tr064.model.Contact;
import de.avm.android.tr064.model.PhoneBook;
import de.usbi.android.util.adapter.ArrayAdapterExt;

/* GUI for the phonebbok (list of contacts)*/
public class PhoneBookActivity extends Activity implements OfflineActivity
{
	private static final String TAG = "PhoneBookActivity";
	
	public static final String EXTRA_CONTACT_DATA_KEY = "CONTACT_DATA";
	public static final String EXTRA_LOCAL_CONTACT_URI = "CONTACT_URI";
	private static final String PREF_PHONEBOOK = "phonebook";
	
	private static final String SAVED_TITLE = "title";
	private static final String SAVED_LOADING = "loading";
	private static final String SAVED_BLANK = "blank";
	private static final String SAVED_SENDING = "sending";

    private static final int LOCAL_CONTACTS_QUERY_TOKEN = 42;

	private static final String LOCAL_CONTACTS = "-1";

	private DataHub mFritzBox = new DataHub();
	private ListView mListView; 
	private TextView mTitle;
	private String mCurrentPhonebook = "";
	
	private LoadTask mLoaderTask = null;
	private WaitDialog mWaitDialog = null;
	private boolean mLoadOnResume = false;
	private boolean mSendOnResume = false;
	private boolean mInitiallyBlank = false;
    private QueryHandler mQueryHandler;
    private ArrayList<String> mOldAttachments = new ArrayList<String>(); 
	private BoxServiceConnection mBoxServiceConnection = new BoxServiceConnection();

	// using savedInstanceState to restore loaded list is far too slow!
	private static ArrayList<Contact> mContacts = null;
	
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.phonebook);
		ResourceHelper.setAltTitleSymbol(this);

        mQueryHandler = new QueryHandler(this);
		
		// Title
        mTitle = ResourceHelper.setTitle(this, R.string.phonebook_label);

		// ListView
		mListView = (ListView)findViewById(R.id.ListViewContent);
		mListView.setSelector(R.drawable.list_selector_background);
		mListView.setOnKeyListener(new OnKeyListener()
		{
			public boolean onKey(View v, int keyCode, KeyEvent event)
			{
				if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER)
				{
					View item = mListView.getSelectedView();
					if (item != null)
						return item.performClick();
				}
				return false;
			}
		});
		mListView.setOnItemClickListener(new AdapterView.OnItemClickListener()
		{
	        public void onItemClick(AdapterView<?> parent, View v, int position, long id)
	        {
	            onListItemClick((ListView)parent, v, position, id);
	        }
	    });

		if (savedInstanceState == null)
		{
			// last used phonebook
			mCurrentPhonebook = PreferenceManager.getDefaultSharedPreferences(this)
					.getString(PREF_PHONEBOOK, "");
			mContacts = null;
			mLoadOnResume = true;
			mInitiallyBlank = true;
		}
		else
		{
			// restore phonebook from prev. instance
			if (mContacts != null)
				mListView.setAdapter(new PhoneBookAdapter(mContacts));
			mCurrentPhonebook = savedInstanceState.getString(PREF_PHONEBOOK);
			if (mTitle != null)
				mTitle.setText(savedInstanceState.getString(SAVED_TITLE));
			mLoadOnResume = (mContacts == null) ||
					savedInstanceState.getBoolean(SAVED_LOADING);
			mSendOnResume = savedInstanceState.getBoolean(SAVED_SENDING); 
			mInitiallyBlank = savedInstanceState.getBoolean(SAVED_BLANK);
		}
	}

	@Override
	protected void onDestroy()
	{
		super.onDestroy();
		if (isFinishing()) mContacts = null;
	}
	
	@Override
	protected void onResume()
	{
		super.onResume();
		if (!mBoxServiceConnection.bindService(getApplicationContext()))
			Log.w(TAG, "Failed to bind to BoxService.");
		if (mLoadOnResume)
		{
			mLoadOnResume = false;
			refreshPhoneBook();
		}
		else if (mSendOnResume)
		{
			sendPhoneBook();
		}
		mSendOnResume = false;
	}	

	@Override
	protected void onPause()
	{
		super.onPause();

		deleteSendAttachments();
		
		dismissWait();
		mLoaderTask = null;
		mBoxServiceConnection.unbindService();
	}

	protected void onSaveInstanceState(Bundle outState)
	{
		outState.putString(PREF_PHONEBOOK, mCurrentPhonebook);
		outState.putString(SAVED_TITLE,
				(mTitle == null) ? "" : mTitle.getText().toString());
		if (mLoaderTask != null)
		{
			if (mLoaderTask.getClass().equals(SendPhonebookTask.class))
				outState.putBoolean(SAVED_SENDING, true);
			else
				outState.putBoolean(SAVED_LOADING, true);
		}
		outState.putBoolean(SAVED_BLANK, mInitiallyBlank);
	}
	
	/**
	 * Load current selected phonebook.
	 * Asks user to choose from available phonebooks, if mCurrentPhonebook
	 * is not available 
	 * Processed in worker thread
	 */
	private void refreshPhoneBook()
	{
		if (!TextUtils.isEmpty(mCurrentPhonebook))
		{
			if (mCurrentPhonebook.equals(LOCAL_CONTACTS))
			{
				showCurrentPhoneBook();
			}
			else if (mLoaderTask == null)
			{
				showWait();
				mLoaderTask = (LoadTask)new LoadListTask().execute(Boolean.FALSE);
			}
		}
		else
		{
			// don't know, what to load
			selectPhoneBook();
		}
	}
	
	/**
	 * Asks user to choose from available phonebooks and loads it.
	 * Processed in worker thread
	 */
	private void selectPhoneBook()
	{
		if (mLoaderTask == null)
		{
			showWait();
			mLoaderTask = (LoadTask)new LoadListTask().execute(Boolean.TRUE);
		}
	}
	
	private void showCurrentPhoneBook()
	{
		if (!TextUtils.isEmpty(mCurrentPhonebook))
		{
			if (mCurrentPhonebook.equals(LOCAL_CONTACTS))
			{
				// local contacts
				dismissWait();
				mInitiallyBlank = false;
				if (mTitle != null) mTitle.setText(R.string.contacts_label);
				mListView.setAdapter(new LocalContactsAdapter(this));
				startLocalContactsQuery();
				if (mSendOnResume) sendPhoneBook();
			}
			else
			{
				// load box' phone book
				showWait();
				mLoaderTask = (LoadTask)new LoadPhonebookTask()
						.execute(mCurrentPhonebook);
			}
		}
		else dismissWait();
	}
	
	/**
	 * Sends contacts of currently shown phonebook via Email
	 * (appended file in box' phonebook export format). Only
	 * available for local contacts.
	 */
	private void sendPhoneBook()
	{
		if (mLoaderTask == null)
		{
			showWait();
			mLoaderTask = (LoadTask)new SendPhonebookTask(this).execute((Object)null);
		}
	}
	
	private void deleteSendAttachments()
	{
		if (mOldAttachments.size() > 0)	
		{
			// TODO test removing export files (don't delete too early!)
//			if (Environment.MEDIA_MOUNTED.equals(Environment
//					.getExternalStorageState()))
//			{
//				for (String fileName : mOldAttachments)
//				{
//					File file = new File(fileName);
//					try
//					{
//						if (file.exists()) file.delete();
//					}
//					catch (Exception e)
//					{
//						// try this as fallback
//						try { file.deleteOnExit(); }
//						catch (Exception exp) { /*ignore*/ }
//					}
//				}
//			}
			mOldAttachments.clear();
		}
	}

    private void onListItemClick(ListView listView, View view, int position, long id)
    {
    	ListAdapter adapter = listView.getAdapter();
    	if (adapter == null) return;
    	
    	Intent intent = null;
    	if (adapter.getClass().equals(PhoneBookAdapter.class))
    	{
	    	Contact contact = (Contact)listView.getItemAtPosition(position);
	    	if (contact != null)
	    	{
	    		intent = new Intent(this, ContactDetailsActivity.class);
	    		intent.putExtra(EXTRA_CONTACT_DATA_KEY, contact);
	    	}
    	}
    	else if (adapter.getClass().equals(LocalContactsAdapter.class))
    	{
    		intent = new Intent(this, ContactDetailsActivity.class);
    		intent.putExtra(EXTRA_LOCAL_CONTACT_URI,
    				((ViewHolder)view.getTag()).Data);
    	}

    	if (intent != null) startActivity(intent);
    }

	/**
	 * Helper for adapters
	 */
	private class ViewHolder
	{
		public TextView Name;
		public String Data = null;
		
		public ViewHolder(View view)
		{
			Name = (TextView)view.findViewById(R.id.ContactName);
		}
	}

	/**
     * List view adapter for box' contacts
     */
	private class PhoneBookAdapter extends ArrayAdapterExt<Contact>
	{
		/**
		 * Instantiates a new phone book adapter.
		 * 
		 * @param contacts
		 *            the contacts
		 */
		public PhoneBookAdapter(ArrayList<Contact> contacts)
		{
			addEntries(contacts);
		}

		@Override
		public View populateView(final Contact item, View view, ViewGroup viewGroup)
		{
			ViewHolder viewHolder; 
			if (view == null)
			{
				view = View.inflate(getBaseContext(), R.layout.t_contactlistitem, null);
				viewHolder = new ViewHolder(view);
				view.setTag(viewHolder);
			}
			else viewHolder = (ViewHolder)view.getTag();

			viewHolder.Name.setText(item.getRealName());

			return view;
		}
	}

    /**
     * Start query for local contacts
     * @throws InvocationTargetException 
     */
    private void startLocalContactsQuery()
    {
    	ListAdapter adapter = mListView.getAdapter();
    	if ((adapter != null) && adapter.getClass().equals(LocalContactsAdapter.class))
    	{
    		((LocalContactsAdapter)adapter).setLoading(true);

            // Cancel any pending queries
            mQueryHandler.cancelOperation(LOCAL_CONTACTS_QUERY_TOKEN);

            LocalContacts localContacts = LocalContacts.getInstance(); 
            mQueryHandler.startQuery(LOCAL_CONTACTS_QUERY_TOKEN, null,
            		localContacts.getSummaryUri(), localContacts.getSummaryProjection(),
            		localContacts.getSelection(), null,
            		localContacts.getSummaryOrder());
    	}
    }
	
    /**
     * List view adapter for local contacts
     */
	private class LocalContactsAdapter extends ResourceCursorAdapter
	{
		private boolean mLoading = true;

        public void setLoading(boolean loading)
        {
            mLoading = loading;
        }
        
        public boolean isLoading()
        {
        	return mLoading;
        }

		public LocalContactsAdapter(Context context)
		{
			super(context, R.layout.t_contactlistitem, null, false);
		}

        /**
         * Requery on background thread when {@link Cursor} changes.
         */
        @Override
        protected void onContentChanged()
        {
            startLocalContactsQuery(); // start async requery
        }

        @Override
        public boolean isEmpty()
        {
        	if (mLoading) return false; // don't show empty state when loading
            return super.isEmpty();
        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent)
        {
            View view = super.newView(context, cursor, parent);

            // Get the views to bind to
            view.setTag(new ViewHolder(view));

            return view;
        }

		@Override
		public void bindView(View view, Context context, Cursor cursor)
		{
            final ViewHolder views = (ViewHolder)view.getTag();

            LocalContacts.Contact contact = LocalContacts
            		.getInstance().getSummaryItem(PhoneBookActivity.this, cursor);

            // store people URI
            views.Data = contact.mUri.toString();

            // Set the name
            if (contact.getName().length() > 0)
            	views.Name.setText(contact.getName());
            else
            	views.Name.setText(R.string.unknown);
		}
	}

    private static final class QueryHandler extends AsyncQueryHandler
    {
    	private final WeakReference<PhoneBookActivity> mParent;

        public QueryHandler(PhoneBookActivity parent)
        {
            super(parent.getContentResolver());
            mParent = new WeakReference<PhoneBookActivity>(parent);
        }

        @Override
        protected void onQueryComplete(int token, Object cookie, Cursor cursor)
        {
        	final PhoneBookActivity parent = mParent.get();
        	if ((parent != null) && !parent.isFinishing())
        	{
            	final ListAdapter adapter = parent.mListView.getAdapter();
            	if ((adapter != null) && adapter.getClass().equals(LocalContactsAdapter.class))
            	{
            		((LocalContactsAdapter)adapter).setLoading(false);
            		((LocalContactsAdapter)adapter).changeCursor(cursor);
            	}
                else cursor.close();
        	}
        }
    }
	
	public static Intent showIntent(Context context)
	{
		if (canShow())
			return new Intent(context, PhoneBookActivity.class)
					.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
		return null; 
	}
	
	public static Boolean canShow()
	{
		Tr064Capabilities capabilities = ComSettingsChecker.getTr064Capabilities();
		return (capabilities != null) &&
				capabilities.has(Tr064Capabilities.Capability.PHONEBOOK);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu)
	{
	    getMenuInflater().inflate(R.menu.phonebook_menu, menu);
		return true;
	}

	@Override
	public boolean onPrepareOptionsMenu (Menu menu)
	{
		boolean canSend = false;
		if (!TextUtils.isEmpty(mCurrentPhonebook) &&
				mCurrentPhonebook.equals(LOCAL_CONTACTS))
		{
			ListAdapter adapter = mListView.getAdapter();
			if ((adapter != null) &&
					adapter.getClass().equals(LocalContactsAdapter.class) &&
					!((LocalContactsAdapter)adapter).isEmpty() &&
					!((LocalContactsAdapter)adapter).isLoading())
				canSend = true;
		}
		menu.findItem(R.id.Send).setEnabled(canSend);
		
		return true;
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item)
	{
		switch (item.getItemId())
		{
			case R.id.Select:
				selectPhoneBook();
				break;
				
			case R.id.Send:
				sendPhoneBook();
				break;
				
			case R.id.Refresh:
				refreshPhoneBook();
				break;
		}
		return true;
	}

	private void onError(LoadTask thread, String message)
	{
		if (mLoaderTask == thread)
		{
			dismissWait();
			mLoaderTask = null;
			
			if (mTitle != null) mTitle.setText(R.string.phonebook_label);
			mContacts = null;
			mListView.setAdapter(null);
			mInitiallyBlank = false;
	
			try
			{
				TextDialog.createOk(this, message).show();
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		}
	}

	private void onIdsLoaded(LoadTask thread, String[] phonebookIds)
	{
		if (mLoaderTask == thread)
		{
			mLoaderTask = null;

			// mCurrentPhonebook still available?
			for (String id : phonebookIds)
				if (mCurrentPhonebook.equals(id))
				{
					showCurrentPhoneBook();
					return;
				}

			dismissWait();
			
			// mCurrentPhonebook is empty or not available anymore
			selectPhoneBook();
		}
	}

	private void onNamesLoaded(LoadTask thread, final String[] phonebookIds,
			String[] phonebookNames)
	{
		if (mLoaderTask == thread)
		{
			if ((mCurrentPhonebook.length() == 0) && (phonebookIds.length == 1))
			{
				// mCurrentPhonebook is empty and there is one book only
				mCurrentPhonebook = phonebookIds[0];
				Editor edit = PreferenceManager
						.getDefaultSharedPreferences(this).edit();
				edit.putString(PREF_PHONEBOOK, mCurrentPhonebook);
				edit.commit();

				// load it
				mLoaderTask = (LoadTask)new LoadPhonebookTask()
						.execute(mCurrentPhonebook);
				return;
			}

			dismissWait();
			mLoaderTask = null;

			// current selected phonebook
			int currentId = -1;
			if (!TextUtils.isEmpty(mCurrentPhonebook))
			{
				if (mCurrentPhonebook.equals(LOCAL_CONTACTS))
				{
					// local contacts
					currentId = phonebookIds.length;
				}
				else
					for (int ii = 0; ii < phonebookIds.length; ii++)
					{
						if (mCurrentPhonebook.equals(phonebookIds[ii]))
						{
							currentId = ii;
							break;
						}
					}
			}

			// add local contacts to list
			String[] displayIds = new String[phonebookNames.length + 1];
			for (int ii = 0; ii < phonebookNames.length; ii++)
				displayIds[ii] = phonebookNames[ii];
			displayIds[phonebookNames.length] = getString(R.string.contacts_label);

			// select phonebook
			new AlertDialog.Builder(this)
					.setTitle(R.string.menu_select_phonebook)
					.setIcon(TextDialog.DEFAULT_EDIT_ICON)
					.setCancelable(true)
					.setInverseBackgroundForced(true)
					.setSingleChoiceItems(displayIds, currentId,
							new DialogInterface.OnClickListener()
					{
						public void onClick(DialogInterface dialog, int item)
						{
							dialog.dismiss();
							
							if (mLoaderTask == null)
							{
								String selected = (item < phonebookIds.length) ?
										phonebookIds[item] : LOCAL_CONTACTS;
								
								// save new selection
								if (!mCurrentPhonebook.equals(selected))
								{
									mCurrentPhonebook = selected;
									Editor edit = PreferenceManager
											.getDefaultSharedPreferences(PhoneBookActivity.this)
											.edit();
									edit.putString(PREF_PHONEBOOK, mCurrentPhonebook);
									edit.commit();

									if (mTitle != null) mTitle.setText(R.string.phonebook_label);
									mContacts = null;
									mListView.setAdapter(null);
									
									// load it
									showCurrentPhoneBook();
								}
							}
						}
					})
					.setOnCancelListener(new DialogInterface.OnCancelListener()
					{
						public void onCancel(DialogInterface dialog)
						{
							// if first loading, close activity
							if (mInitiallyBlank)
								PhoneBookActivity.this.finish();
						}
					})
					.show();
		}
	}

	private void onBookLoaded(LoadTask thread, PhoneBook phonebook)
	{
		if (mLoaderTask == thread)
		{
			dismissWait();
			mLoaderTask = null;
			
			if (mCurrentPhonebook.equals(phonebook.getId()))
			{
				if (mTitle != null)
				{
					String title = getString(R.string.phonebook_label);
					if (phonebook.getName().startsWith(title))
						mTitle.setText(phonebook.getName());
					else
						mTitle.setText(title + " " + phonebook.getName());
				}
		
				mContacts = new ArrayList<Contact>();
				mContacts.addAll(phonebook.getContacts());
				Collections.sort(mContacts, new Comparator<Contact>()
				{
					public int compare(Contact contact1, Contact contact2)
					{
						return contact1.getRealName().compareToIgnoreCase(
								contact2.getRealName());
					}
				});
				mListView.setAdapter(new PhoneBookAdapter(mContacts));
				mInitiallyBlank = false;
			}
		}
	}
	
	private void onSent(LoadTask thread, Integer error, Intent sendIntent)
	{
		if (mLoaderTask == thread)
		{
			dismissWait();
			mLoaderTask = null;

			if (error.intValue() == 0)
			{
				try
				{
					startActivity(sendIntent);
				}
				catch (ActivityNotFoundException exp)
				{
					exp.printStackTrace();
					error = Integer.valueOf(
							R.string.contacts_send_error_emailclient);
				}
			}

			if (error.intValue() != 0)
			{
				try
				{
					TextDialog.createOk(this, getString(error.intValue())).show();
				}
				catch(Exception e)
				{
					e.printStackTrace();
				}
			}
		}		
	}

	private void showWait()
	{
		if (mWaitDialog == null)
		{
			mWaitDialog = WaitDialog.show(this, R.string.wait_dialog,
					new DialogInterface.OnCancelListener()
			{
				public void onCancel(DialogInterface dialog)
				{
					if (dialog == mWaitDialog)
					{
						// cancel pending load
						mWaitDialog = null;
						dialog.dismiss();
						mLoaderTask = null;
						
						// if first loading, close activity
						if (mInitiallyBlank)
							PhoneBookActivity.this.finish();
					}
					else dialog.dismiss();
				}
			});
		}
	}
	
	private void dismissWait()
	{
		if (mWaitDialog != null)
		{
			mWaitDialog.dismiss();
			mWaitDialog = null;
		}
	}
	
	private interface LoadTask
	{
	}
	
	private class LoadListTask extends AsyncTask<Boolean, Integer,
			LoadListTask.NamesList> implements LoadTask
	{
		private Exception mError = null;
		
		public class NamesList
		{
			String[] ids = null;
			String[] names = null;
		}

		@Override
		protected NamesList doInBackground(Boolean... params)
		{
			try
			{
				NamesList list = new NamesList();
				list.ids = mFritzBox.getPhoneBookList(PhoneBookActivity.this);
				
				if (params[0] && list.ids.length > 0)
				{
					list.names = new String[list.ids.length];
					for (int ii = 0; ii < list.ids.length; ii++)
						list.names[ii] = mFritzBox.getPhoneBookName(list.ids[ii],
								PhoneBookActivity.this); 
				}
				
				return list;
			}
			catch(Exception exp)
			{
				mError = exp;
				exp.printStackTrace();
				if (IOException.class.isAssignableFrom(exp.getClass()))
				{
					IBoxService srv = mBoxServiceConnection.getService();
					if (srv != null) srv.reconnect();
				}
				return null;
			}
		}
		
		@Override
		protected void onPostExecute(NamesList list)
		{
			super.onPostExecute(list);
			if (list == null)
			{
				if (SslErrorException.isSslError(mError))
					onError(this, SslErrorException.getDisplayMessage(
							PhoneBookActivity.this, mError));
				else
					onError(this, PhoneBookActivity.this.
							getString(R.string.soap_tranfer_failed));
			}
			else if (list.ids.length < 1)
				onError(this, PhoneBookActivity.this.
						getString(R.string.phonebook_empty_list));
			else if (list.names == null)
				onIdsLoaded(this, list.ids);
			else
				onNamesLoaded(this, list.ids, list.names);
		}
	}

	private class LoadPhonebookTask extends AsyncTask<String, Integer,
			PhoneBook> implements LoadTask
	{
		private Exception mError = null;
		
		@Override
		protected PhoneBook doInBackground(String... params)
		{
			try
			{
				return mFritzBox.getPhoneBook(params[0], PhoneBookActivity.this);
			}
			catch(Exception exp)
			{
				mError = exp;
				exp.printStackTrace();
				if (IOException.class.isAssignableFrom(exp.getClass()))
				{
					IBoxService srv = mBoxServiceConnection.getService();
					if (srv != null) srv.reconnect();
				}
				return null;
			}
		}
		
		@Override
		protected void onPostExecute(PhoneBook phonebook)
		{
			super.onPostExecute(phonebook);
			if (phonebook == null)
			{
				if (SslErrorException.isSslError(mError))
					onError(this, SslErrorException.getDisplayMessage(
							PhoneBookActivity.this, mError));
				else
					onError(this, PhoneBookActivity.this.
							getString(R.string.soap_tranfer_failed));
			}
			else onBookLoaded(this, phonebook);
		}
	}

	private class SendPhonebookTask extends SendLocalContactsTask
			implements LoadTask
	{
		public SendPhonebookTask(Context context)
		{
			super(context);
		}
		
		@Override
		protected void onPostExecute(Integer error)
		{
			super.onPostExecute(error);

			String filePath = getExportFilePath();
			if (!TextUtils.isEmpty(filePath))
				mOldAttachments.add(filePath);
			
			onSent(this, error, getSendIntent());
		}
	}
}
