/*
 * 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.settings.inputmethod;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.AsyncTaskLoader;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.Loader;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.hardware.input.InputManager.InputDeviceListener;
import android.hardware.input.KeyboardLayout;
import android.os.Bundle;
import android.view.InputDevice;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckedTextView;
import android.widget.RadioButton;
import android.widget.TextView;

import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;

import java.util.ArrayList;
import java.util.Collections;

public class KeyboardLayoutDialogFragment extends InstrumentedDialogFragment
        implements InputDeviceListener, LoaderCallbacks<KeyboardLayoutDialogFragment.Keyboards> {
    private static final String KEY_INPUT_DEVICE_IDENTIFIER = "inputDeviceIdentifier";

    private InputDeviceIdentifier mInputDeviceIdentifier;
    private int mInputDeviceId = -1;
    private InputManager mIm;
    private KeyboardLayoutAdapter mAdapter;

    public KeyboardLayoutDialogFragment() {
    }

    public KeyboardLayoutDialogFragment(InputDeviceIdentifier inputDeviceIdentifier) {
        mInputDeviceIdentifier = inputDeviceIdentifier;
    }


    @Override
    public int getMetricsCategory() {
        return MetricsProto.MetricsEvent.DIALOG_KEYBOARD_LAYOUT;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        Context context = activity.getBaseContext();
        mIm = (InputManager)context.getSystemService(Context.INPUT_SERVICE);
        mAdapter = new KeyboardLayoutAdapter(context);
    }

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

        if (savedInstanceState != null) {
            mInputDeviceIdentifier = savedInstanceState.getParcelable(KEY_INPUT_DEVICE_IDENTIFIER);
        }

        getLoaderManager().initLoader(0, null, this);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelable(KEY_INPUT_DEVICE_IDENTIFIER, mInputDeviceIdentifier);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Context context = getActivity();
        LayoutInflater inflater = LayoutInflater.from(context);
        AlertDialog.Builder builder = new AlertDialog.Builder(context)
            .setTitle(R.string.keyboard_layout_dialog_title)
            .setPositiveButton(R.string.keyboard_layout_dialog_setup_button,
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            onSetupLayoutsButtonClicked();
                        }
                    })
            .setSingleChoiceItems(mAdapter, -1,
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            onKeyboardLayoutClicked(which);
                        }
                    })
            .setView(inflater.inflate(R.layout.keyboard_layout_dialog_switch_hint, null));
        updateSwitchHintVisibility();
        return builder.create();
    }

    @Override
    public void onResume() {
        super.onResume();

        mIm.registerInputDeviceListener(this, null);

        InputDevice inputDevice =
                mIm.getInputDeviceByDescriptor(mInputDeviceIdentifier.getDescriptor());
        if (inputDevice == null) {
            dismiss();
            return;
        }
        mInputDeviceId = inputDevice.getId();
    }

    @Override
    public void onPause() {
        mIm.unregisterInputDeviceListener(this);
        mInputDeviceId = -1;

        super.onPause();
    }

    @Override
    public void onCancel(DialogInterface dialog) {
        super.onCancel(dialog);
        dismiss();
    }

    private void onSetupLayoutsButtonClicked() {
        ((OnSetupKeyboardLayoutsListener)getTargetFragment()).onSetupKeyboardLayouts(
                mInputDeviceIdentifier);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        show(getActivity().getFragmentManager(), "layout");
    }

    private void onKeyboardLayoutClicked(int which) {
        if (which >= 0 && which < mAdapter.getCount()) {
            KeyboardLayout keyboardLayout = mAdapter.getItem(which);
            if (keyboardLayout != null) {
                mIm.setCurrentKeyboardLayoutForInputDevice(mInputDeviceIdentifier,
                        keyboardLayout.getDescriptor());
            }
            dismiss();
        }
    }

    @Override
    public Loader<Keyboards> onCreateLoader(int id, Bundle args) {
        return new KeyboardLayoutLoader(getActivity().getBaseContext(), mInputDeviceIdentifier);
    }

    @Override
    public void onLoadFinished(Loader<Keyboards> loader, Keyboards data) {
        mAdapter.clear();
        mAdapter.addAll(data.keyboardLayouts);
        mAdapter.setCheckedItem(data.current);
        AlertDialog dialog = (AlertDialog)getDialog();
        if (dialog != null) {
            dialog.getListView().setItemChecked(data.current, true);
        }
        updateSwitchHintVisibility();
    }

    @Override
    public void onLoaderReset(Loader<Keyboards> loader) {
        mAdapter.clear();
        updateSwitchHintVisibility();
    }

    @Override
    public void onInputDeviceAdded(int deviceId) {
    }

    @Override
    public void onInputDeviceChanged(int deviceId) {
        if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
            getLoaderManager().restartLoader(0, null, this);
        }
    }

    @Override
    public void onInputDeviceRemoved(int deviceId) {
        if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
            dismiss();
        }
    }

    private void updateSwitchHintVisibility() {
        AlertDialog dialog = (AlertDialog)getDialog();
        if (dialog != null) {
            View customPanel = dialog.findViewById(com.android.internal.R.id.customPanel);
            customPanel.setVisibility(mAdapter.getCount() > 1 ? View.VISIBLE : View.GONE);
        }
    }

    private static final class KeyboardLayoutAdapter extends ArrayAdapter<KeyboardLayout> {
        private final LayoutInflater mInflater;
        private int mCheckedItem = -1;

        public KeyboardLayoutAdapter(Context context) {
            super(context, com.android.internal.R.layout.simple_list_item_2_single_choice);
            mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }

        public void setCheckedItem(int position) {
            mCheckedItem = position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            KeyboardLayout item = getItem(position);
            String label, collection;
            if (item != null) {
                label = item.getLabel();
                collection = item.getCollection();
            } else {
                label = getContext().getString(R.string.keyboard_layout_default_label);
                collection = "";
            }

            boolean checked = (position == mCheckedItem);
            if (collection.isEmpty()) {
                return inflateOneLine(convertView, parent, label, checked);
            } else {
                return inflateTwoLine(convertView, parent, label, collection, checked);
            }
        }

        private View inflateOneLine(View convertView, ViewGroup parent,
                String label, boolean checked) {
            View view = convertView;
            if (view == null || isTwoLine(view)) {
                view = mInflater.inflate(
                        com.android.internal.R.layout.simple_list_item_single_choice,
                        parent, false);
                setTwoLine(view, false);
            }
            CheckedTextView headline = (CheckedTextView) view.findViewById(android.R.id.text1);
            headline.setText(label);
            headline.setChecked(checked);
            return view;
        }

        private View inflateTwoLine(View convertView, ViewGroup parent,
                String label, String collection, boolean checked) {
            View view = convertView;
            if (view == null || !isTwoLine(view)) {
                view = mInflater.inflate(
                        com.android.internal.R.layout.simple_list_item_2_single_choice,
                        parent, false);
                setTwoLine(view, true);
            }
            TextView headline = (TextView) view.findViewById(android.R.id.text1);
            TextView subText = (TextView) view.findViewById(android.R.id.text2);
            RadioButton radioButton =
                    (RadioButton)view.findViewById(com.android.internal.R.id.radio);
            headline.setText(label);
            subText.setText(collection);
            radioButton.setChecked(checked);
            return view;
        }

        private static boolean isTwoLine(View view) {
            return view.getTag() == Boolean.TRUE;
        }

        private static void setTwoLine(View view, boolean twoLine) {
            view.setTag(Boolean.valueOf(twoLine));
        }
    }

    private static final class KeyboardLayoutLoader extends AsyncTaskLoader<Keyboards> {
        private final InputDeviceIdentifier mInputDeviceIdentifier;

        public KeyboardLayoutLoader(Context context, InputDeviceIdentifier inputDeviceIdentifier) {
            super(context);
            mInputDeviceIdentifier = inputDeviceIdentifier;
        }

        @Override
        public Keyboards loadInBackground() {
            Keyboards keyboards = new Keyboards();
            InputManager im = (InputManager)getContext().getSystemService(Context.INPUT_SERVICE);
            String[] keyboardLayoutDescriptors = im.getEnabledKeyboardLayoutsForInputDevice(
                    mInputDeviceIdentifier);
            for (String keyboardLayoutDescriptor : keyboardLayoutDescriptors) {
                KeyboardLayout keyboardLayout = im.getKeyboardLayout(keyboardLayoutDescriptor);
                if (keyboardLayout != null) {
                    keyboards.keyboardLayouts.add(keyboardLayout);
                }
            }
            Collections.sort(keyboards.keyboardLayouts);

            String currentKeyboardLayoutDescriptor =
                    im.getCurrentKeyboardLayoutForInputDevice(mInputDeviceIdentifier);
            if (currentKeyboardLayoutDescriptor != null) {
                final int numKeyboardLayouts = keyboards.keyboardLayouts.size();
                for (int i = 0; i < numKeyboardLayouts; i++) {
                    if (keyboards.keyboardLayouts.get(i).getDescriptor().equals(
                            currentKeyboardLayoutDescriptor)) {
                        keyboards.current = i;
                        break;
                    }
                }
            }

            if (keyboards.keyboardLayouts.isEmpty()) {
                keyboards.keyboardLayouts.add(null); // default layout
                keyboards.current = 0;
            }
            return keyboards;
        }

        @Override
        protected void onStartLoading() {
            super.onStartLoading();
            forceLoad();
        }

        @Override
        protected void onStopLoading() {
            super.onStopLoading();
            cancelLoad();
        }
    }

    public static final class Keyboards {
        public final ArrayList<KeyboardLayout> keyboardLayouts = new ArrayList<KeyboardLayout>();
        public int current = -1;
    }

    public interface OnSetupKeyboardLayoutsListener {
        public void onSetupKeyboardLayouts(InputDeviceIdentifier mInputDeviceIdentifier);
    }
}
