/* 
 * 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 android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.preference.Preference.OnPreferenceChangeListener;
import android.text.TextUtils;
import android.util.Log;
import android.widget.ListView;
import de.avm.android.fritzapp.R;
import de.avm.android.fritzapp.com.ComSettingsChecker;
import de.avm.android.fritzapp.service.BoxService;
import de.avm.android.fritzapp.service.NewOutgoingCallReceiver;
import de.avm.android.fritzapp.util.BuildHelper;
import de.avm.android.fritzapp.util.PackageManagerHelper;
import de.avm.android.fritzapp.util.ResourceHelper;

public class SettingsExtendedActivity extends PreferenceActivity
{
	private static final String TAG = "SettingsExtendedActivity";
	
	public static final String PREF_NET_UNRESTRICTED = "net_unrestricted";
	public static final boolean DEFAULT_NET_UNRESTRICTED = false;
	public static final String PREF_CALL_INTENT_HTC = "call_intent_htc"; // old preference
	public static final String PREF_CALL_INTEGRATION = "call_integration";
	public static final IntegrationMode PREF_CALL_INTEGRATION_DEFAULT;
	public static final String PREF_DIMM_ONLY = "dimm_only";
	public static final String PREF_MIC_44 = "mic_44";
	public static final String PREF_MIC_VOL = "mic_vol";

	public enum IntegrationMode
	{
		DEFAULT, HTC_ASK, HTC_AUTO;
		
		public static IntegrationMode fromString(String value)
		{
			try
			{
				return IntegrationMode.valueOf(value);
			}
			catch(Exception e)
			{
				return DEFAULT;
			}
		}
	};

	static
	{
		PREF_CALL_INTEGRATION_DEFAULT = (BuildHelper.isCallIntentHtcDefault()) ?
				IntegrationMode.HTC_ASK : IntegrationMode.DEFAULT;
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);

		setContentView(R.layout.settings);
		ListView preferenceView = (ListView)findViewById(android.R.id.list);
		preferenceView.setSelector(R.drawable.list_selector_background);

		PreferenceScreen screen = createPreferenceScreen(savedInstanceState);
		screen.setPersistent(true);
		screen.bind(preferenceView);
		preferenceView.setAdapter(screen.getRootAdapter());
		setPreferenceScreen(screen);

		// Title
		ResourceHelper.setAltTitleSymbol(this);
		ResourceHelper.setTitle(this, R.string.pref_extended_title);
	}

	private PreferenceScreen createPreferenceScreen(Bundle savedInstanceState)
	{
		PreferenceScreen root = getPreferenceManager()
				.createPreferenceScreen(this);

		// network restriction (only in lab build)
		CheckBoxPreference checkboxPreference =
				new CheckBoxPreference(this);
		checkboxPreference.setKey(PREF_NET_UNRESTRICTED);
		checkboxPreference.setDefaultValue(DEFAULT_NET_UNRESTRICTED);
		checkboxPreference.setTitle(
				R.string.pref_extended_unrestricted);
		checkboxPreference.setSummary(
				R.string.pref_extended_unrestricted_desc);
		checkboxPreference.setOnPreferenceChangeListener(
				new OnPreferenceChangeListener()
		{
			public boolean onPreferenceChange(Preference preference,
					Object newValue)
			{

				runOnUiThread(new Runnable()
				{
					public void run()
					{
						onNetRestrictionChanged();
					}
				});
				return true;
			}
		});
		root.addPreference(checkboxPreference);
		
		// call intent mode
		IntegrationPreference preference = new IntegrationPreference(this);
		preference.setKey(PREF_CALL_INTEGRATION);
		preference.setDefaultValue(PREF_CALL_INTEGRATION_DEFAULT.toString());
		preference.setTitle(R.string.pref_extended_integration);
		preference.setDialogTitle(R.string.pref_extended_integration);
		root.addPreference(preference);
		
		if (BuildHelper.hasDimOnlyOption())
		{
			// dim only
			checkboxPreference = new CheckBoxPreference(this);
			checkboxPreference.setKey(PREF_DIMM_ONLY);
			checkboxPreference.setDefaultValue(BuildHelper.isDimOnlyDevice());
			checkboxPreference.setTitle(R.string.pref_dimm_only);
			checkboxPreference.setSummary(R.string.pref_dimm_only_desc);
			root.addPreference(checkboxPreference);
		}
		
		// mic with 44,1kHz
		checkboxPreference = new CheckBoxPreference(this);
		checkboxPreference.setKey(PREF_MIC_44);
		checkboxPreference.setDefaultValue(BuildHelper.isRecordingWith44kHzDefault());
		checkboxPreference.setTitle(R.string.pref_mic_44);
		checkboxPreference.setSummary(R.string.pref_mic_44_desc);
		root.addPreference(checkboxPreference);
		
		// mic resampler volume
		MicVolumePreference volumePreference = new MicVolumePreference(this);
		volumePreference.setKey(PREF_MIC_VOL);
		volumePreference.setDefaultValue(BuildHelper.getResamplerVolume());
		volumePreference.setTitle(R.string.pref_mic_vol);
		volumePreference.setDialogTitle(R.string.pref_mic_vol);
		root.addPreference(volumePreference);
		
		return root;
	}
	
	private void onNetRestrictionChanged()
	{
		// re-search if not connected, deactivated WLAN-only and no WLAN connected
		if (!isWlanOnly(this) &&
				(ComSettingsChecker.getBoxInfo() != null))
		{
			NetworkInfo networkInfo = ((ConnectivityManager)
					getSystemService(Context.CONNECTIVITY_SERVICE))
					.getActiveNetworkInfo();
			if ((networkInfo == null) ||
					(networkInfo.getType() != ConnectivityManager.TYPE_WIFI))
			{
				Intent serviceIntent = new Intent(this, BoxService.class);
				serviceIntent.putExtra(BoxService.EXTRA_COMMAND,
						BoxService.Command.RECONNECT.ordinal());
				startService(serviceIntent);
			}
		}
	}
	
	private class IntegrationPreference extends ListPreference
			implements OnPreferenceChangeListener
	{
		private final String[] mSummaries;
		
		public IntegrationPreference(Context context)
		{
			super(context);
			
			setEntries(R.array.pref_extended_integrationmode);
			int entriesCount = getEntries().length;

			IntegrationMode[] modes = IntegrationMode.values();
			if (modes.length != entriesCount)
				throw new ArrayIndexOutOfBoundsException();
			String[] modeStrings = new String[modes.length];
			for (int ii = modes.length -1; ii >= 0; ii--)
				modeStrings[ii] = modes[ii].toString();
			setEntryValues(modeStrings);

			mSummaries = context.getResources().getStringArray(
					R.array.pref_extended_integrationmode_desc);
			if (mSummaries.length < entriesCount)
				throw new ArrayIndexOutOfBoundsException();

			setOnPreferenceChangeListener(this);
		}

		@Override
		protected void onSetInitialValue(boolean restoreValue, Object defaultValue)
		{
			super.onSetInitialValue(restoreValue, defaultValue);
			if (restoreValue)
			{
				try
				{
					IntegrationMode.valueOf(getValue());
				}
				catch(Exception e)
				{
					// restored value is invalid
					setValue(PREF_CALL_INTEGRATION_DEFAULT.toString());
				}
			}
			setSummary(mSummaries[IntegrationMode.fromString(getValue()).ordinal()]);
		}
		
		public boolean onPreferenceChange(Preference preference, Object newValue)
		{
			IntegrationMode mode = IntegrationMode.fromString(newValue.toString());
			try
			{
				PackageManagerHelper.setEnableReceiver(SettingsExtendedActivity.this,
						NewOutgoingCallReceiver.class,mode != IntegrationMode.DEFAULT);
			}
			catch (NameNotFoundException e)
			{
				Log.e(TAG, "Failed to enable/disable NewOutgoingCallReceiver", e);
			}
			setSummary(mSummaries[mode.ordinal()]);
			return true;
		}
	}

	/**
	 * Checks if connection to Box with connected WLAN only
	 * 
	 * @param context valid context to access preferences
	 * @return true if WLAN only
	 */
	public static boolean isWlanOnly(Context context)
	{
		return !PreferenceManager.getDefaultSharedPreferences(context)
				.getBoolean(PREF_NET_UNRESTRICTED, DEFAULT_NET_UNRESTRICTED);
	}

	public static IntegrationMode getIntegrationMode(Context context)
	{
		String mode = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(PREF_CALL_INTEGRATION, null);
		if (TextUtils.isEmpty(mode)) return PREF_CALL_INTEGRATION_DEFAULT;
		return IntegrationMode.fromString(mode);
	}
	
	public static boolean isDimOnly(Context context)
	{
		return BuildHelper.hasDimOnlyOption() &&
				PreferenceManager.getDefaultSharedPreferences(context)
						.getBoolean(PREF_DIMM_ONLY, BuildHelper.isDimOnlyDevice());
	}
	
	public static boolean isRecordingWith44kHz(Context context)
	{
		return PreferenceManager.getDefaultSharedPreferences(context)
				.getBoolean(PREF_MIC_44, BuildHelper.isRecordingWith44kHzDefault());
	}
	
	public static int getResamplerVolume(Context context)
	{
		return PreferenceManager.getDefaultSharedPreferences(context)
				.getInt(PREF_MIC_VOL, BuildHelper.getResamplerVolume());
	}

	/**
	 * Preparations on settings to do on app's start
	 * @param context context for reading and writing the settings
	 * @param firstRun true for first run after install
	 */
	public static void prepareSettings(Context context, boolean firstRun)
	{
		SharedPreferences prefs = PreferenceManager
				.getDefaultSharedPreferences(context);
		Editor editor = null;

		if (prefs.contains(PREF_CALL_INTENT_HTC))
		{
			// import from/remove old setting
			editor = prefs.edit();
			if (!prefs.contains(PREF_CALL_INTEGRATION))
			{
				boolean oldHtcOption = prefs.getBoolean(PREF_CALL_INTENT_HTC, false);
				editor.putString(PREF_CALL_INTEGRATION, (oldHtcOption) ?
						IntegrationMode.HTC_ASK.toString() :
						IntegrationMode.DEFAULT.toString());
			}
			editor.remove(PREF_CALL_INTENT_HTC);
		}
		
		if (!BuildHelper.hasDimOnlyOption() &&
				prefs.contains(PREF_DIMM_ONLY))
		{
			// remove old setting
			if (editor == null) editor = prefs.edit();
			editor.remove(PREF_DIMM_ONLY);
		}
		
		if (editor != null) editor.commit();
		try
		{
			PackageManagerHelper.setEnableReceiver(context,
					NewOutgoingCallReceiver.class,
					getIntegrationMode(context) != IntegrationMode.DEFAULT);
		}
		catch (NameNotFoundException e)
		{
			Log.e(TAG, "Failed to enable/disable NewOutgoingCallReceiver", e);
		}
	}
}
