/* 
 * Copyright 2015 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.service;

import java.util.List;

import de.avm.android.fritzapp.R;
import de.avm.android.fritzapp.gui.SettingsRouteExceptionsActivity;
import de.avm.android.fritzapp.gui.TextDialog;
import de.avm.android.fritzapp.util.PhoneNumberHelper;
import de.avm.fundamentals.logger.FileLog;

import android.app.Activity;
import android.app.Dialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;

/**
 * Activity to start outgoing calls
 */
public class MobileFallbackActivity extends Activity
{
	private static final String TAG = "MobileFallbackActivity";

	private static final String EXTRA_FALLBACK_NUMBER =
			"de.avm.android.fritzapp.service.FALLBACK_NUMBER";
	private static final String EXTRA_ASK_FOR_FALLBACK =
			"de.avm.android.fritzapp.service.ASK_FOR_FALLBACK";

	private static final String SAVED_TARGET = "target";
	private static final int DIALOG_FALLBACK = 1;
	private static final int DIALOG_ERROR = 2;
	private static final int DIALOG_NO_MOBILE = 3;
	private static final int DIALOG_NOTRUF = 4;
	
	private Intent mTarget = null;
	private boolean mIsEmergencyNumber = false;
	
	/**
	 * Sends intent for fallback to mobile phone
	 * 
	 * When no mobile phone app available, show error message. If ask, show
	 * "no SIP", otherwise "no mobile phone".
	 * 
	 * @param context
	 * 		context to send from
	 * @param number
	 * 		phone number
	 * @param ask
	 * 		true to ask user for fallback to mobile phone, otherwise do it
	 * 		without consent
	 */
	public static void sendMobileFallbackIntent(Context context, String number, boolean ask)
	{
		Intent intent = new Intent(context, MobileFallbackActivity.class)
				.putExtra(EXTRA_FALLBACK_NUMBER, number)
				.putExtra(EXTRA_ASK_FOR_FALLBACK, ask)
				.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP |
						Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
		if (!Activity.class.isAssignableFrom(context.getClass()))
			intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		context.startActivity(intent);
	}

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);

		if (savedInstanceState == null)
		{
			Intent intent = getIntent();
			if ((intent != null) &&
					intent.hasExtra(EXTRA_FALLBACK_NUMBER))
			{
				// error message or fallback request
				String number = intent.getStringExtra(EXTRA_FALLBACK_NUMBER);
				boolean internalNumber = PhoneNumberHelper.isInternalNumber(number);
				mIsEmergencyNumber = PhoneNumberUtils.isEmergencyNumber(number);
				boolean ask = intent.getBooleanExtra(EXTRA_ASK_FOR_FALLBACK, false) &&
						SettingsRouteExceptionsActivity.isAskForMobileFallback(this);
				if (!TextUtils.isEmpty(number) && !internalNumber)
					setTarget(number);
				
				if (mTarget == null)
				{
					showDialog((ask || internalNumber) ?
							DIALOG_ERROR : DIALOG_NO_MOBILE);
				}
				else if (ask)
				{
					showDialog(DIALOG_FALLBACK);
				}
				else
				{
					onMobileFallback();
				}
				return;
			}
			
			setResult(Activity.RESULT_CANCELED);
			finish();
		}
		else
		{
			mTarget = savedInstanceState.getParcelable(SAVED_TARGET);
		}
	}
	
	@Override
	protected void onSaveInstanceState(Bundle outState)
	{
		if (mTarget != null) outState.putParcelable(SAVED_TARGET, mTarget);
	}
	
	private void setTarget(String number)
	{
		final List<ResolveInfo> resolveInfos = getPackageManager()
				.queryIntentActivities(OutgoingCallActivity.createCallIntent(number),
						PackageManager.MATCH_DEFAULT_ONLY);
		if (resolveInfos != null)
			for(ResolveInfo info : resolveInfos)
			{
				ActivityInfo activity = info.activityInfo;
				if (activity.packageName.equals("com.android.phone") ||
						activity.packageName.equals("com.android.contacts") ||
						activity.packageName.equals("com.android.server.telecom"))
				{
					mTarget = OutgoingCallActivity.createCallIntent(number)
							.setComponent(new ComponentName(activity.packageName,
									activity.name));
					FileLog.d(TAG, "  mTarget == " + mTarget);
					break;
				}
			}
	}

	@Override
	protected Dialog onCreateDialog (final int id)
	{
		super.onCreateDialog (id);
		
		switch (id)
		{
			case DIALOG_FALLBACK:
				return TextDialog.create(this,
						        TextDialog.getDefaultTitle(this),
						        String.format(getString(R.string.callroute_fallback),
								getString(R.string.regno)),
                                TextDialog.DEFAULT_MESSAGE_ICON)
						.setPositiveButton(R.string.intent_once,
								new DialogInterface.OnClickListener()
						{
							public void onClick(DialogInterface dialog, int which)
							{
								removeDialog(DIALOG_FALLBACK);
								dialog.dismiss();
								onMobileFallback();
							}
						})
						.setNeutralButton(R.string.intent_always,
								new DialogInterface.OnClickListener()
						{
							public void onClick(DialogInterface dialog, int which)
							{
								removeDialog(DIALOG_FALLBACK);
								SettingsRouteExceptionsActivity.setIsAskForMobileFallback(
										MobileFallbackActivity.this, false);
								onMobileFallback();
							}
						})
						.setOnCancelListener(new DialogInterface.OnCancelListener()
						{
							public void onCancel(DialogInterface dialog)
							{
								removeDialog(DIALOG_FALLBACK);
					    		setResult(Activity.RESULT_CANCELED);
								finish();
							}
						})
						.create();
			
			case DIALOG_ERROR:
			case DIALOG_NO_MOBILE:
				return TextDialog.create(this,
						        TextDialog.getDefaultTitle(this),
						        getString((id == DIALOG_NO_MOBILE) ?
								        R.string.callroute_no_fallback : R.string.regno),
                                TextDialog.DEFAULT_MESSAGE_ICON)
						.setPositiveButton(android.R.string.ok,
								new DialogInterface.OnClickListener()
						{
							public void onClick(DialogInterface dialog, int which)
							{
								removeDialog(id);
					    		setResult(Activity.RESULT_OK);
								finish();
							}
						})
						.setOnCancelListener(new DialogInterface.OnCancelListener()
						{
							public void onCancel(DialogInterface dialog)
							{
								removeDialog(id);
					    		setResult(Activity.RESULT_OK);
								finish();
							}
						})
						.create();

			case DIALOG_NOTRUF:
				return TextDialog.create(this,
						        TextDialog.getDefaultTitle(this),
						        getString(R.string.call_notruf),
                                TextDialog.DEFAULT_MESSAGE_ICON)
						.setPositiveButton(android.R.string.ok,
								new DialogInterface.OnClickListener()
						{
							public void onClick(DialogInterface dialog, int which)
							{
								removeDialog(id);
								doMobileFallback();
							}
						})
						.setOnCancelListener(new DialogInterface.OnCancelListener()
						{
							public void onCancel(DialogInterface dialog)
							{
								removeDialog(id);
								doMobileFallback();
							}
						})
						.create();
		}
		
		return null;
	}
	
	private void onMobileFallback()
	{
		if (mIsEmergencyNumber)
		{
			getPackageManager().clearPackagePreferredActivities(getPackageName());
			showDialog(DIALOG_NOTRUF);
			return;
		}
		
		doMobileFallback();
	}
	
	private void doMobileFallback()
	{
		try
		{
			NewOutgoingCallReceiver.ignore(this, mTarget);
			startActivity(mTarget);
    		setResult(Activity.RESULT_OK);
		}
		catch (Exception e)
		{
			FileLog.e(TAG, "Cannot invoke phone call.", e);
    		setResult(Activity.RESULT_CANCELED);
		}
		finish();
	}
}
