/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.inputmethod.latin.settings;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceGroup;
import android.support.v4.view.ViewCompat;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodSubtype;
import android.widget.Toast;

import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.RichInputMethodManager;
import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
import com.android.inputmethod.latin.utils.DialogUtils;
import com.android.inputmethod.latin.utils.IntentUtils;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;

import java.util.ArrayList;

public final class CustomInputStyleSettingsFragment extends PreferenceFragment
        implements CustomInputStylePreference.Listener {
    private static final String TAG = CustomInputStyleSettingsFragment.class.getSimpleName();
    // Note: We would like to turn this debug flag true in order to see what input styles are
    // defined in a bug-report.
    private static final boolean DEBUG_CUSTOM_INPUT_STYLES = true;

    private RichInputMethodManager mRichImm;
    private SharedPreferences mPrefs;
    private CustomInputStylePreference.SubtypeLocaleAdapter mSubtypeLocaleAdapter;
    private CustomInputStylePreference.KeyboardLayoutSetAdapter mKeyboardLayoutSetAdapter;

    private boolean mIsAddingNewSubtype;
    private AlertDialog mSubtypeEnablerNotificationDialog;
    private String mSubtypePreferenceKeyForSubtypeEnabler;

    private static final String KEY_IS_ADDING_NEW_SUBTYPE = "is_adding_new_subtype";
    private static final String KEY_IS_SUBTYPE_ENABLER_NOTIFICATION_DIALOG_OPEN =
            "is_subtype_enabler_notification_dialog_open";
    private static final String KEY_SUBTYPE_FOR_SUBTYPE_ENABLER = "subtype_for_subtype_enabler";

    public CustomInputStyleSettingsFragment() {
        // Empty constructor for fragment generation.
    }

    static void updateCustomInputStylesSummary(final Preference pref) {
        // When we are called from the Settings application but we are not already running, some
        // singleton and utility classes may not have been initialized.  We have to call
        // initialization method of these classes here. See {@link LatinIME#onCreate()}.
        SubtypeLocaleUtils.init(pref.getContext());

        final Resources res = pref.getContext().getResources();
        final SharedPreferences prefs = pref.getSharedPreferences();
        final String prefSubtype = Settings.readPrefAdditionalSubtypes(prefs, res);
        final InputMethodSubtype[] subtypes =
                AdditionalSubtypeUtils.createAdditionalSubtypesArray(prefSubtype);
        final ArrayList<String> subtypeNames = new ArrayList<>();
        for (final InputMethodSubtype subtype : subtypes) {
            subtypeNames.add(SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype));
        }
        // TODO: A delimiter of custom input styles should be localized.
        pref.setSummary(TextUtils.join(", ", subtypeNames));
    }

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

        mPrefs = getPreferenceManager().getSharedPreferences();
        RichInputMethodManager.init(getActivity());
        mRichImm = RichInputMethodManager.getInstance();
        addPreferencesFromResource(R.xml.additional_subtype_settings);
        setHasOptionsMenu(true);
    }

    @Override
    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
            final Bundle savedInstanceState) {
        final View view = super.onCreateView(inflater, container, savedInstanceState);
        // For correct display in RTL locales, we need to set the layout direction of the
        // fragment's top view.
        ViewCompat.setLayoutDirection(view, ViewCompat.LAYOUT_DIRECTION_LOCALE);
        return view;
    }

    @Override
    public void onActivityCreated(final Bundle savedInstanceState) {
        final Context context = getActivity();
        mSubtypeLocaleAdapter = new CustomInputStylePreference.SubtypeLocaleAdapter(context);
        mKeyboardLayoutSetAdapter =
                new CustomInputStylePreference.KeyboardLayoutSetAdapter(context);

        final String prefSubtypes =
                Settings.readPrefAdditionalSubtypes(mPrefs, getResources());
        if (DEBUG_CUSTOM_INPUT_STYLES) {
            Log.i(TAG, "Load custom input styles: " + prefSubtypes);
        }
        setPrefSubtypes(prefSubtypes, context);

        mIsAddingNewSubtype = (savedInstanceState != null)
                && savedInstanceState.containsKey(KEY_IS_ADDING_NEW_SUBTYPE);
        if (mIsAddingNewSubtype) {
            getPreferenceScreen().addPreference(
                    CustomInputStylePreference.newIncompleteSubtypePreference(context, this));
        }

        super.onActivityCreated(savedInstanceState);

        if (savedInstanceState != null && savedInstanceState.containsKey(
                KEY_IS_SUBTYPE_ENABLER_NOTIFICATION_DIALOG_OPEN)) {
            mSubtypePreferenceKeyForSubtypeEnabler = savedInstanceState.getString(
                    KEY_SUBTYPE_FOR_SUBTYPE_ENABLER);
            mSubtypeEnablerNotificationDialog = createDialog();
            mSubtypeEnablerNotificationDialog.show();
        }
    }

    @Override
    public void onSaveInstanceState(final Bundle outState) {
        super.onSaveInstanceState(outState);
        if (mIsAddingNewSubtype) {
            outState.putBoolean(KEY_IS_ADDING_NEW_SUBTYPE, true);
        }
        if (mSubtypeEnablerNotificationDialog != null
                && mSubtypeEnablerNotificationDialog.isShowing()) {
            outState.putBoolean(KEY_IS_SUBTYPE_ENABLER_NOTIFICATION_DIALOG_OPEN, true);
            outState.putString(
                    KEY_SUBTYPE_FOR_SUBTYPE_ENABLER, mSubtypePreferenceKeyForSubtypeEnabler);
        }
    }

    @Override
    public void onRemoveCustomInputStyle(final CustomInputStylePreference stylePref) {
        mIsAddingNewSubtype = false;
        final PreferenceGroup group = getPreferenceScreen();
        group.removePreference(stylePref);
        mRichImm.setAdditionalInputMethodSubtypes(getSubtypes());
    }

    @Override
    public void onSaveCustomInputStyle(final CustomInputStylePreference stylePref) {
        final InputMethodSubtype subtype = stylePref.getSubtype();
        if (!stylePref.hasBeenModified()) {
            return;
        }
        if (findDuplicatedSubtype(subtype) == null) {
            mRichImm.setAdditionalInputMethodSubtypes(getSubtypes());
            return;
        }

        // Saved subtype is duplicated.
        final PreferenceGroup group = getPreferenceScreen();
        group.removePreference(stylePref);
        stylePref.revert();
        group.addPreference(stylePref);
        showSubtypeAlreadyExistsToast(subtype);
    }

    @Override
    public void onAddCustomInputStyle(final CustomInputStylePreference stylePref) {
        mIsAddingNewSubtype = false;
        final InputMethodSubtype subtype = stylePref.getSubtype();
        if (findDuplicatedSubtype(subtype) == null) {
            mRichImm.setAdditionalInputMethodSubtypes(getSubtypes());
            mSubtypePreferenceKeyForSubtypeEnabler = stylePref.getKey();
            mSubtypeEnablerNotificationDialog = createDialog();
            mSubtypeEnablerNotificationDialog.show();
            return;
        }

        // Newly added subtype is duplicated.
        final PreferenceGroup group = getPreferenceScreen();
        group.removePreference(stylePref);
        showSubtypeAlreadyExistsToast(subtype);
    }

    @Override
    public CustomInputStylePreference.SubtypeLocaleAdapter getSubtypeLocaleAdapter() {
        return mSubtypeLocaleAdapter;
    }

    @Override
    public CustomInputStylePreference.KeyboardLayoutSetAdapter getKeyboardLayoutSetAdapter() {
        return mKeyboardLayoutSetAdapter;
    }

    private void showSubtypeAlreadyExistsToast(final InputMethodSubtype subtype) {
        final Context context = getActivity();
        final Resources res = context.getResources();
        final String message = res.getString(R.string.custom_input_style_already_exists,
                SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype));
        Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
    }

    private InputMethodSubtype findDuplicatedSubtype(final InputMethodSubtype subtype) {
        final String localeString = subtype.getLocale();
        final String keyboardLayoutSetName = SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype);
        return mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
                localeString, keyboardLayoutSetName);
    }

    private AlertDialog createDialog() {
        final String imeId = mRichImm.getInputMethodIdOfThisIme();
        final AlertDialog.Builder builder = new AlertDialog.Builder(
                DialogUtils.getPlatformDialogThemeContext(getActivity()));
        builder.setTitle(R.string.custom_input_styles_title)
                .setMessage(R.string.custom_input_style_note_message)
                .setNegativeButton(R.string.not_now, null)
                .setPositiveButton(R.string.enable, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        final Intent intent = IntentUtils.getInputLanguageSelectionIntent(
                                imeId,
                                Intent.FLAG_ACTIVITY_NEW_TASK
                                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        // TODO: Add newly adding subtype to extra value of the intent as a hint
                        // for the input language selection activity.
                        // intent.putExtra("newlyAddedSubtype", subtypePref.getSubtype());
                        startActivity(intent);
                    }
                });

        return builder.create();
    }

    private void setPrefSubtypes(final String prefSubtypes, final Context context) {
        final PreferenceGroup group = getPreferenceScreen();
        group.removeAll();
        final InputMethodSubtype[] subtypesArray =
                AdditionalSubtypeUtils.createAdditionalSubtypesArray(prefSubtypes);
        for (final InputMethodSubtype subtype : subtypesArray) {
            final CustomInputStylePreference pref =
                    new CustomInputStylePreference(context, subtype, this);
            group.addPreference(pref);
        }
    }

    private InputMethodSubtype[] getSubtypes() {
        final PreferenceGroup group = getPreferenceScreen();
        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
        final int count = group.getPreferenceCount();
        for (int i = 0; i < count; i++) {
            final Preference pref = group.getPreference(i);
            if (pref instanceof CustomInputStylePreference) {
                final CustomInputStylePreference subtypePref = (CustomInputStylePreference)pref;
                // We should not save newly adding subtype to preference because it is incomplete.
                if (subtypePref.isIncomplete()) continue;
                subtypes.add(subtypePref.getSubtype());
            }
        }
        return subtypes.toArray(new InputMethodSubtype[subtypes.size()]);
    }

    @Override
    public void onPause() {
        super.onPause();
        final String oldSubtypes = Settings.readPrefAdditionalSubtypes(mPrefs, getResources());
        final InputMethodSubtype[] subtypes = getSubtypes();
        final String prefSubtypes = AdditionalSubtypeUtils.createPrefSubtypes(subtypes);
        if (DEBUG_CUSTOM_INPUT_STYLES) {
            Log.i(TAG, "Save custom input styles: " + prefSubtypes);
        }
        if (prefSubtypes.equals(oldSubtypes)) {
            return;
        }
        Settings.writePrefAdditionalSubtypes(mPrefs, prefSubtypes);
        mRichImm.setAdditionalInputMethodSubtypes(subtypes);
    }

    @Override
    public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
        inflater.inflate(R.menu.add_style, menu);
    }

    @Override
    public boolean onOptionsItemSelected(final MenuItem item) {
        final int itemId = item.getItemId();
        if (itemId == R.id.action_add_style) {
            final CustomInputStylePreference newSubtype =
                    CustomInputStylePreference.newIncompleteSubtypePreference(getActivity(), this);
            getPreferenceScreen().addPreference(newSubtype);
            newSubtype.show();
            mIsAddingNewSubtype = true;
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}
