/*
 * Copyright (C) 2006 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 android.widget;

import android.content.Context;
import android.view.KeyEvent;
import android.text.Editable;
import android.text.InputFilter;
import android.text.Selection;
import android.text.Spannable;
import android.text.Spanned;
import android.text.TextWatcher;
import android.text.method.DialerKeyListener;
import android.text.method.KeyListener;
import android.text.method.TextKeyListener;
import android.util.AttributeSet;
import android.view.View;
import android.graphics.Rect;



public class DialerFilter extends RelativeLayout
{
    public DialerFilter(Context context) {
        super(context);
    }

    public DialerFilter(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        // Setup the filter view
        mInputFilters = new InputFilter[] { new InputFilter.AllCaps() };

        mHint = (EditText) findViewById(com.android.internal.R.id.hint);
        if (mHint == null) {
            throw new IllegalStateException("DialerFilter must have a child EditText named hint");
        }
        mHint.setFilters(mInputFilters);

        mLetters = mHint;
        mLetters.setKeyListener(TextKeyListener.getInstance());
        mLetters.setMovementMethod(null);
        mLetters.setFocusable(false);

        // Setup the digits view
        mPrimary = (EditText) findViewById(com.android.internal.R.id.primary);
        if (mPrimary == null) {
            throw new IllegalStateException("DialerFilter must have a child EditText named primary");
        }
        mPrimary.setFilters(mInputFilters);

        mDigits = mPrimary;
        mDigits.setKeyListener(DialerKeyListener.getInstance());
        mDigits.setMovementMethod(null);
        mDigits.setFocusable(false);

        // Look for an icon
        mIcon = (ImageView) findViewById(com.android.internal.R.id.icon);

        // Setup focus & highlight for this view
        setFocusable(true);

        // XXX Force the mode to QWERTY for now, since 12-key isn't supported
        mIsQwerty = true;
        setMode(DIGITS_AND_LETTERS);
    }

    /**
     * Only show the icon view when focused, if there is one.
     */
    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);

        if (mIcon != null) {
            mIcon.setVisibility(focused ? View.VISIBLE : View.GONE);
        }
    }


    public boolean isQwertyKeyboard() {
        return mIsQwerty;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        boolean handled = false;

        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_UP:
            case KeyEvent.KEYCODE_DPAD_DOWN:
            case KeyEvent.KEYCODE_DPAD_LEFT:
            case KeyEvent.KEYCODE_DPAD_RIGHT:
            case KeyEvent.KEYCODE_ENTER:
            case KeyEvent.KEYCODE_DPAD_CENTER:
                break;

            case KeyEvent.KEYCODE_DEL:
                switch (mMode) {
                    case DIGITS_AND_LETTERS:
                        handled = mDigits.onKeyDown(keyCode, event);
                        handled &= mLetters.onKeyDown(keyCode, event);
                        break;

                    case DIGITS_AND_LETTERS_NO_DIGITS:
                        handled = mLetters.onKeyDown(keyCode, event);
                        if (mLetters.getText().length() == mDigits.getText().length()) {
                            setMode(DIGITS_AND_LETTERS);
                        }
                        break;

                    case DIGITS_AND_LETTERS_NO_LETTERS:
                        if (mDigits.getText().length() == mLetters.getText().length()) {
                            mLetters.onKeyDown(keyCode, event);
                            setMode(DIGITS_AND_LETTERS);
                        }
                        handled = mDigits.onKeyDown(keyCode, event);
                        break;

                    case DIGITS_ONLY:
                        handled = mDigits.onKeyDown(keyCode, event);
                        break;

                    case LETTERS_ONLY:
                        handled = mLetters.onKeyDown(keyCode, event);
                        break;
                }
                break;

            default:
                //mIsQwerty = msg.getKeyIsQwertyKeyboard();

                switch (mMode) {
                    case DIGITS_AND_LETTERS:
                        handled = mLetters.onKeyDown(keyCode, event);

                        // pass this throw so the shift state is correct (for example,
                        // on a standard QWERTY keyboard, * and 8 are on the same key)
                        if (KeyEvent.isModifierKey(keyCode)) {
                            mDigits.onKeyDown(keyCode, event);
                            handled = true;
                            break;
                        }

                        // Only check to see if the digit is valid if the key is a printing key
                        // in the TextKeyListener. This prevents us from hiding the digits
                        // line when keys like UP and DOWN are hit.
                        // XXX note that KEYCODE_TAB is special-cased here for 
                        // devices that share tab and 0 on a single key.
                        boolean isPrint = event.isPrintingKey();
                        if (isPrint || keyCode == KeyEvent.KEYCODE_SPACE
                                || keyCode == KeyEvent.KEYCODE_TAB) {
                            char c = event.getMatch(DialerKeyListener.CHARACTERS);
                            if (c != 0) {
                                handled &= mDigits.onKeyDown(keyCode, event);
                            } else {
                                setMode(DIGITS_AND_LETTERS_NO_DIGITS);
                            }
                        }
                        break;

                    case DIGITS_AND_LETTERS_NO_LETTERS:
                    case DIGITS_ONLY:
                        handled = mDigits.onKeyDown(keyCode, event);
                        break;

                    case DIGITS_AND_LETTERS_NO_DIGITS:
                    case LETTERS_ONLY:
                        handled = mLetters.onKeyDown(keyCode, event);
                        break;
                }
        }

        if (!handled) {
            return super.onKeyDown(keyCode, event);
        } else {
            return true;
        }
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        boolean a = mLetters.onKeyUp(keyCode, event);
        boolean b = mDigits.onKeyUp(keyCode, event);
        return a || b;
    }

    public int getMode() {
        return mMode;
    }

    /**
     * Change the mode of the widget.
     *
     * @param newMode The mode to switch to.
     */
    public void setMode(int newMode) {
        switch (newMode) {
            case DIGITS_AND_LETTERS:
                makeDigitsPrimary();
                mLetters.setVisibility(View.VISIBLE);
                mDigits.setVisibility(View.VISIBLE);
                break;

            case DIGITS_ONLY:
                makeDigitsPrimary();
                mLetters.setVisibility(View.GONE);
                mDigits.setVisibility(View.VISIBLE);
                break;

            case LETTERS_ONLY:
                makeLettersPrimary();
                mLetters.setVisibility(View.VISIBLE);
                mDigits.setVisibility(View.GONE);
                break;

            case DIGITS_AND_LETTERS_NO_LETTERS:
                makeDigitsPrimary();
                mLetters.setVisibility(View.INVISIBLE);
                mDigits.setVisibility(View.VISIBLE);
                break;

            case DIGITS_AND_LETTERS_NO_DIGITS:
                makeLettersPrimary();
                mLetters.setVisibility(View.VISIBLE);
                mDigits.setVisibility(View.INVISIBLE);
                break;

        }
        int oldMode = mMode;
        mMode = newMode;
        onModeChange(oldMode, newMode);
    }

    private void makeLettersPrimary() {
        if (mPrimary == mDigits) {
            swapPrimaryAndHint(true);
        }
    }

    private void makeDigitsPrimary() {
        if (mPrimary == mLetters) {
            swapPrimaryAndHint(false);
        }
    }

    private void swapPrimaryAndHint(boolean makeLettersPrimary) {
        Editable lettersText = mLetters.getText();
        Editable digitsText = mDigits.getText();
        KeyListener lettersInput = mLetters.getKeyListener();
        KeyListener digitsInput = mDigits.getKeyListener();

        if (makeLettersPrimary) {
            mLetters = mPrimary;
            mDigits = mHint;
        } else {
            mLetters = mHint;
            mDigits = mPrimary;
        }

        mLetters.setKeyListener(lettersInput);
        mLetters.setText(lettersText);
        lettersText = mLetters.getText();
        Selection.setSelection(lettersText, lettersText.length());

        mDigits.setKeyListener(digitsInput);
        mDigits.setText(digitsText);
        digitsText = mDigits.getText();
        Selection.setSelection(digitsText, digitsText.length());

        // Reset the filters
        mPrimary.setFilters(mInputFilters);
        mHint.setFilters(mInputFilters);
    }


    public CharSequence getLetters() {
        if (mLetters.getVisibility() == View.VISIBLE) {
            return mLetters.getText();
        } else {
            return "";
        }
    }

    public CharSequence getDigits() {
        if (mDigits.getVisibility() == View.VISIBLE) {
            return mDigits.getText();
        } else {
            return "";
        }
    }

    public CharSequence getFilterText() {
        if (mMode != DIGITS_ONLY) {
            return getLetters();
        } else {
            return getDigits();
        }
    }

    public void append(String text) {
        switch (mMode) {
            case DIGITS_AND_LETTERS:
                mDigits.getText().append(text);
                mLetters.getText().append(text);
                break;

            case DIGITS_AND_LETTERS_NO_LETTERS:
            case DIGITS_ONLY:
                mDigits.getText().append(text);
                break;

            case DIGITS_AND_LETTERS_NO_DIGITS:
            case LETTERS_ONLY:
                mLetters.getText().append(text);
                break;
        }
    }

    /**
     * Clears both the digits and the filter text.
     */
    public void clearText() {
        Editable text;

        text = mLetters.getText();
        text.clear();

        text = mDigits.getText();
        text.clear();

        // Reset the mode based on the hardware type
        if (mIsQwerty) {
            setMode(DIGITS_AND_LETTERS);
        } else {
            setMode(DIGITS_ONLY);
        }
    }

    public void setLettersWatcher(TextWatcher watcher) {
        CharSequence text = mLetters.getText();
        Spannable span = (Spannable)text;
        span.setSpan(watcher, 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
    }

    public void setDigitsWatcher(TextWatcher watcher) {
        CharSequence text = mDigits.getText();
        Spannable span = (Spannable)text;
        span.setSpan(watcher, 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
    }

    public void setFilterWatcher(TextWatcher watcher) {
        if (mMode != DIGITS_ONLY) {
            setLettersWatcher(watcher);
        } else {
            setDigitsWatcher(watcher);
        }
    }

    public void removeFilterWatcher(TextWatcher watcher) {
        Spannable text;
        if (mMode != DIGITS_ONLY) {
            text = mLetters.getText();
        } else {
            text = mDigits.getText();
        }
        text.removeSpan(watcher);
    }

    /**
     * Called right after the mode changes to give subclasses the option to
     * restyle, etc.
     */
    protected void onModeChange(int oldMode, int newMode) {
    }

    /** This mode has both lines */
    public static final int DIGITS_AND_LETTERS = 1;
    /** This mode is when after starting in {@link #DIGITS_AND_LETTERS} mode the filter
     *  has removed all possibility of the digits matching, leaving only the letters line */
    public static final int DIGITS_AND_LETTERS_NO_DIGITS = 2;
    /** This mode is when after starting in {@link #DIGITS_AND_LETTERS} mode the filter
     *  has removed all possibility of the letters matching, leaving only the digits line */
    public static final int DIGITS_AND_LETTERS_NO_LETTERS = 3;
    /** This mode has only the digits line */
    public static final int DIGITS_ONLY = 4;
    /** This mode has only the letters line */
    public static final int LETTERS_ONLY = 5;

    EditText mLetters;
    EditText mDigits;
    EditText mPrimary;
    EditText mHint;
    InputFilter mInputFilters[];
    ImageView mIcon;
    int mMode;
    private boolean mIsQwerty;
}
