/*
 * Copyright (C) 2009 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.customlocale2;


import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Locale;

import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.IActivityManager;
import android.app.ListActivity;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.view.ContextMenu;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.AdapterContextMenuInfo;

/**
 * Displays the list of system locales as well as maintain a custom list of user
 * locales. The user can select a locale and apply it or it can create or remove
 * a custom locale.
 */
public class CustomLocaleActivity extends ListActivity {

    private static final String TAG = "CustomLocale";
    private static final boolean DEBUG = true;

    private static final int DLG_REMOVE_ID = 0;

    private static final String CUSTOM_LOCALES_SEP = " ";
    private static final String CUSTOM_LOCALES = "custom_locales";

    /** Request code returned when the NewLocaleDialog activity finishes. */
    private static final int UPDATE_LIST = 42;
    /** Menu item id for applying a locale */
    private static final int MENU_APPLY = 43;
    /** Menu item id for removing a custom locale */
    private static final int MENU_REMOVE = 44;

    /** List view displaying system and custom locales. */
    private ListView mListView;
    /** Textview used to display current locale */
    private TextView mCurrentLocaleTextView;
    /** Private shared preferences of this activity. */
    private SharedPreferences mPrefs;

    private Button mRemoveLocaleButton;
    private Button mSelectLocaleButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mPrefs = getPreferences(MODE_PRIVATE);

        Button addLocaleButton = (Button) findViewById(R.id.add_new_locale_button);
        mRemoveLocaleButton = (Button) findViewById(R.id.remove_locale_button);
        mSelectLocaleButton = (Button) findViewById(R.id.select_locale_button);

        addLocaleButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                onAddNewLocale();
            }
        });

        mRemoveLocaleButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showDialog(DLG_REMOVE_ID);
            }
        });

        mSelectLocaleButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onSelectLocale();
            }
        });

        mListView = (ListView) findViewById(android.R.id.list);
        mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        mListView.setItemsCanFocus(false);
        mListView.setFocusable(true);
        mListView.setFocusableInTouchMode(true);
        mListView.requestFocus();
        setupLocaleList();

        mCurrentLocaleTextView = (TextView) findViewById(R.id.current_locale);
        displayCurrentLocale();
    }

    @Override
    protected void onResume() {
        super.onResume();
        updateLocaleButtons();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == UPDATE_LIST && resultCode == RESULT_OK && data != null) {
            String locale = data.getExtras().getString(NewLocaleDialog.INTENT_EXTRA_LOCALE);
            if (locale != null && locale.length() > 0) {
                // Get current custom locale list
                String customLocales = mPrefs.getString(CUSTOM_LOCALES, null);

                // Update
                if (customLocales == null) {
                    customLocales = locale;
                } else {
                    customLocales += CUSTOM_LOCALES_SEP + locale;
                }

                // Save prefs
                if (DEBUG) {
                    Log.d(TAG, "add/customLocales: " + customLocales);
                }
                mPrefs.edit().putString(CUSTOM_LOCALES, customLocales).commit();

                Toast.makeText(this,
                               getString(R.string.added_custom_locale_1s, locale),
                               Toast.LENGTH_SHORT)
                     .show();

                // Update list view
                setupLocaleList();

                // Find the item to select it in the list view
                checkLocaleInList(locale);

                if (data.getExtras().getBoolean(NewLocaleDialog.INTENT_EXTRA_SELECT)) {
                    changeSystemLocale(locale);
                }
            }
        }
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        updateLocaleButtons();
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);

        if (menuInfo instanceof AdapterContextMenuInfo) {
            int position = ((AdapterContextMenuInfo) menuInfo).position;
            Object o = mListView.getItemAtPosition(position);
            if (o instanceof LocaleInfo) {
                if (((LocaleInfo) o).isCustom()) {
                    menu.setHeaderTitle("System Locale");
                    menu.add(0, MENU_APPLY, 0, "Apply");
                } else {
                    menu.setHeaderTitle("Custom Locale");
                    menu.add(0, MENU_APPLY, 0, "Apply");
                    menu.add(0, MENU_REMOVE, 0, "Remove");
                }
            }
        }
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        if (id == DLG_REMOVE_ID) {
            return createRemoveLocaleDialog();
        }
        return super.onCreateDialog(id);
    }

    //--- private parts ---

    private void setupLocaleList() {
        if (DEBUG) {
            Log.d(TAG, "Update locate list");
        }

        ArrayList<LocaleInfo> data = new ArrayList<LocaleInfo>();

        // Insert all system locales
        String[] locales = getAssets().getLocales();
        for (String locale : locales) {
            if (locale != null && locale.length() > 0) {
                Locale loc = new Locale(locale);
                data.add(new LocaleInfo(locale, loc.getDisplayName()));
            }
        }
        locales = null;

        // Insert all custom locales
        String customLocales = mPrefs.getString(CUSTOM_LOCALES, "");
        if (DEBUG) {
            Log.d(TAG, "customLocales: " + customLocales);
        }
        for (String locale : customLocales.split(CUSTOM_LOCALES_SEP)) {
            if (locale != null && locale.length() > 0) {
                Locale loc = new Locale(locale);
                data.add(new LocaleInfo(
                                locale,
                                loc.getDisplayName(),
                                true /*custom*/));
            }
        }

        // Sort all locales by code
        Collections.sort(data, new Comparator<LocaleInfo>() {
            public int compare(LocaleInfo lhs, LocaleInfo rhs) {
                return lhs.getLocale().compareTo(rhs.getLocale());
            }
        });

        // Update the list view adapter
        mListView.setAdapter(new ArrayAdapter<LocaleInfo>(
                        this,
                        android.R.layout.simple_list_item_single_choice,
                        data));
        updateLocaleButtons();
    }

    private void changeSystemLocale(String locale) {
        if (ChangeLocale.changeSystemLocale(locale)) {
            Toast.makeText(this,
                            getString(R.string.select_locale_1s, locale),
                            Toast.LENGTH_SHORT)
                 .show();
        }
    }

    private void displayCurrentLocale() {
        try {
            IActivityManager am = ActivityManager.getService();
            Configuration config = am.getConfiguration();

            if (config.locale != null) {
                String text = String.format("%1$s - %2$s",
                        config.locale.toString(),
                        config.locale.getDisplayName());
                mCurrentLocaleTextView.setText(text);

                checkLocaleInList(config.locale.toString());
            }
        } catch (RemoteException e) {
            if (DEBUG) {
                Log.e(TAG, "get current locale failed", e);
            }
        }
    }

    /** Find the locale by code to select it in the list view */
    private void checkLocaleInList(String locale) {
        ListAdapter a = mListView.getAdapter();
        for (int i = 0; i < a.getCount(); i++) {
            Object o = a.getItem(i);
            if (o instanceof LocaleInfo) {
                String code = ((LocaleInfo) o).getLocale();
                if (code != null && code.equals(locale)) {
                    mListView.setSelection(i);
                    mListView.clearChoices();
                    mListView.setItemChecked(i, true);
                    updateLocaleButtons();
                    break;
                }
            }
        }
    }

    private LocaleInfo getCheckedLocale() {
        int pos = mListView.getCheckedItemPosition();
        ListAdapter a = mListView.getAdapter();
        int n = a.getCount();
        if (pos >= 0 && pos < n) {
            Object o = a.getItem(pos);
            if (o instanceof LocaleInfo) {
                return (LocaleInfo) o;
            }
        }

        return null;
    }

    /** Update the Select/Remove buttons based on the currently checked locale. */
    private void updateLocaleButtons() {
        LocaleInfo info = getCheckedLocale();
        if (info != null) {
            // Enable it
            mSelectLocaleButton.setEnabled(true);
            mSelectLocaleButton.setText(
                getString(R.string.select_locale_1s_button, info.getLocale()));

            // Enable the remove button only for custom locales and set the tag to the locale
            mRemoveLocaleButton.setEnabled(info.isCustom());
        } else {
            // If nothing is selected, disable the buttons
            mSelectLocaleButton.setEnabled(false);
            mSelectLocaleButton.setText(R.string.select_locale_button);

            mRemoveLocaleButton.setEnabled(false);
        }
    }

    /** Invoked by the button "Add new..." */
    private void onAddNewLocale() {
        Intent i = new Intent(CustomLocaleActivity.this, NewLocaleDialog.class);
        startActivityForResult(i, UPDATE_LIST);
    }

    /** Invoked by the button Select / mSelectLocaleButton */
    private void onSelectLocale() {
        LocaleInfo info = getCheckedLocale();
        if (info != null) {
            changeSystemLocale(info.getLocale());
        }
    }

    /**
     * Invoked by the button Remove / mRemoveLocaleButton.
     * Creates a dialog to ask for confirmation before actually remove the custom locale.
     */
    private Dialog createRemoveLocaleDialog() {

        LocaleInfo info = getCheckedLocale();
        final String localeToRemove = info == null ? "<error>" : info.getLocale();

        AlertDialog.Builder b = new AlertDialog.Builder(this);
        b.setMessage(getString(R.string.confirm_remove_locale_1s, localeToRemove));
        b.setCancelable(false);
        b.setPositiveButton(R.string.confirm_remove_locale_yes,
            new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    removeCustomLocale(localeToRemove);
                    dismissDialog(DLG_REMOVE_ID);
                }
        });
        b.setNegativeButton(R.string.confirm_remove_locale_no,
            new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dismissDialog(DLG_REMOVE_ID);
                }
        });

        return b.create();
    }

    private void removeCustomLocale(String localeToRemove) {
        // Get current custom locale list
        String oldLocales = mPrefs.getString(CUSTOM_LOCALES, "");

        if (DEBUG) {
            Log.d(TAG, "Remove " + localeToRemove + " from custom locales: " + oldLocales);
        }

        // Update
        StringBuilder sb = new StringBuilder();
        for (String locale : oldLocales.split(CUSTOM_LOCALES_SEP)) {
            if (locale != null && locale.length() > 0 && !locale.equals(localeToRemove)) {
                if (sb.length() > 0) {
                    sb.append(CUSTOM_LOCALES_SEP);
                }
                sb.append(locale);
            }
        }

        String newLocales = sb.toString();
        if (!newLocales.equals(oldLocales)) {
            // Save prefs
            boolean ok = mPrefs.edit().putString(CUSTOM_LOCALES, newLocales).commit();
            if (DEBUG) {
                Log.d(TAG, "Prefs commit:" + Boolean.toString(ok) + ". Saved: " + newLocales);
            }

            Toast.makeText(this,
                            getString(R.string.removed_custom_locale_1s, localeToRemove),
                            Toast.LENGTH_SHORT)
                 .show();

            // Update list view
            setupLocaleList();
        }
    }

    /**
     * Immutable structure that holds the information displayed by a list view item.
     */
    private static class LocaleInfo {
        private final String mLocale;
        private final String mDisplayName;
        private final boolean mIsCustom;

        public LocaleInfo(String locale, String displayName, boolean isCustom) {
            mLocale = locale;
            mDisplayName = displayName;
            mIsCustom = isCustom;
        }

        public LocaleInfo(String locale, String displayName) {
            this(locale, displayName, false /*custom*/);
        }

        public String getLocale() {
            return mLocale;
        }

        public boolean isCustom() {
            return mIsCustom;
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(mLocale)
              .append(" - ")
              .append(mDisplayName);
            if (mIsCustom) {
                sb.append(" [Custom]");
            }
            return sb.toString();
        }
    }
}
