/* 
 * 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.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.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.preference.Preference.OnPreferenceChangeListener;
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.NetworkChangedHandler;
import de.avm.android.fritzapp.service.NewOutgoingCallReceiver;
import de.avm.android.fritzapp.util.AudioEffects;
import de.avm.android.fritzapp.util.BuildHelper;
import de.avm.android.fritzapp.util.PackageManagerHelper;
import de.avm.android.fritzapp.util.ResourceHelper;
import de.avm.fundamentals.logger.FileLog;

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

	private enum IntegrationMode
	{
		DEFAULT, HTC_ASK, HTC_AUTO;
		/*
		 * HTC_ASK and HTC_AUTO are treated as the one and only HTC integration
		 * The option is a check box now. To leave preference string untouched,
		 * class IntegrationPreference maps the values
		 */
		
		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.setTitle(this, R.string.pref_extended_title);
	}

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

        CheckBoxPreference checkboxPreference;
        if (hasWlanOnlyOption())
        {
            // network restriction (only in lab build)
            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
		root.addPreference(new IntegrationPreference(this));
		
		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);
		
		// audio effects
		if (AudioEffects.isAvailable(AudioEffects.FLAG_AEC))
		{
			checkboxPreference = new CheckBoxPreference(this);
			checkboxPreference.setKey(PREF_EFFECTS);
			checkboxPreference.setDefaultValue(DEFAULT_EFFECTS);
			checkboxPreference.setTitle(R.string.pref_extended_effects);
			checkboxPreference.setSummary((AudioEffects.isAvailable(AudioEffects.FLAG_NR)) ?
					R.string.pref_extended_effects3 : R.string.pref_extended_effects2);
			checkboxPreference.setEnabled(!SettingsTestActivity.isLoopback(this));
			root.addPreference(checkboxPreference);
		}
		
		return root;
	}
	
	private void onNetRestrictionChanged()
	{
		// re-search if not connected, deactivated WLAN-only and no WLAN connected
		if (hasWlanOnlyOption() && !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 CheckBoxPreference
			implements OnPreferenceChangeListener
	{
		public IntegrationPreference(Context context)
		{
			super(context);

			setTitle(R.string.pref_extended_integration);
			setSummary(R.string.pref_extended_integration2);
			setPersistent(false);
			setChecked(isHtcIntegrationMode(SettingsExtendedActivity.this));
			
			setOnPreferenceChangeListener(this);
		}
		
		public boolean onPreferenceChange(Preference preference, Object newValue)
		{
			Editor editor = PreferenceManager.getDefaultSharedPreferences(
					SettingsExtendedActivity.this).edit();
			editor.putString(PREF_CALL_INTEGRATION, (((Boolean)newValue) ?
					IntegrationMode.HTC_ASK.toString() : IntegrationMode.DEFAULT.toString()));
			editor.apply();

			try
			{
				PackageManagerHelper.setEnableReceiver(SettingsExtendedActivity.this,
						NewOutgoingCallReceiver.class, (Boolean)newValue);
			}
			catch (NameNotFoundException e)
			{
				FileLog.e(TAG, "Failed to enable/disable NewOutgoingCallReceiver", e);
			}
			return true;
		}
	}

    /**
     * Checks if WLAN only option is used
     *
     * @return true if WLAN only is used
     */
    public static boolean hasWlanOnlyOption()
    {
        return NetworkChangedHandler.usesWlanOnlyOption();
    }

    /**
     * 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 boolean isHtcIntegrationMode(Context context)
	{
		String mode = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(PREF_CALL_INTEGRATION,
						PREF_CALL_INTEGRATION_DEFAULT.toString());
		return IntegrationMode.fromString(mode) != IntegrationMode.DEFAULT;
	}
	
	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());
	}

	public static boolean isEffects(Context context)
	{
		return PreferenceManager.getDefaultSharedPreferences(context)
				.getBoolean(PREF_EFFECTS, DEFAULT_EFFECTS);
	}

	/**
	 * 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.apply();
		try
		{
			PackageManagerHelper.setEnableReceiver(context,
					NewOutgoingCallReceiver.class,
					isHtcIntegrationMode(context));
		}
		catch (NameNotFoundException e)
		{
			FileLog.e(TAG, "Failed to enable/disable NewOutgoingCallReceiver", e);
		}
	}
}
