package com.xplora.xpsettings.SKKeyboard;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.text.Editable;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.widget.EditText;
import android.widget.Editor;
import android.widget.RelativeLayout;
import android.widget.ScrollView;

import com.xplora.xpsettings.R;

public class SKKeyboardUtils implements View.OnTouchListener {
    @SuppressLint("StaticFieldLeak")
    private static SKKeyboardUtils instance = null;
    private RelativeLayout mKeyboardLayout = null;
    private RelativeLayout mKeyboard_bottom = null;
    private KeyboardView mMainView = null;
    private KeyboardView mSwitchView = null;
    private EditText mEditText = null;
    private Context mContext = null;
    private boolean isShiftLocked = false;

    public static SKKeyboardUtils getInstance() {
        if (instance == null) {
            instance = new SKKeyboardUtils();
        }
        return instance;
    }

    public void createSKKeyboard(Context context, EditText editText) {
        mEditText = editText;
        if (context != mContext || mKeyboardLayout == null) {
            initSKKeyboard(context);
            changeKeyboardStyle(mEditText.getInputType());
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    public void initSKKeyboard(Context context) {
        mContext = context;
        isShiftLocked = false;

        try {
            KeyboardView.OnKeyboardActionListener mListener = new KeyboardView.OnKeyboardActionListener() {
                @Override
                public void onKey(int primaryCode, int[] keyCodes) {
                    if (primaryCode <= KEY_CODES.KEY_SWITCH_shift_abc.CODES) {
                        switchKeyboard(primaryCode);
                    } else {
                        updateText(primaryCode);
                    }
                }

                @Override
                public void onPress(int primaryCode) { }
                @Override
                public void onRelease(int primaryCode) { }
                @Override
                public void onText(CharSequence charSequence) { }
                @Override
                public void swipeLeft() { }
                @Override
                public void swipeRight() { }
                @Override
                public void swipeDown() { }
                @Override
                public void swipeUp() { }
            };

            mKeyboardLayout = ((Activity) context).findViewById(R.id.sk_keyboard);
            ScrollView scrollView = ((Activity) context).findViewById(R.id.keyboard_scrollview);
            scrollView.setOnTouchListener(this);
            mKeyboard_bottom = ((Activity) context).findViewById(R.id.keyboard_bottom);

            mMainView = ((Activity) context).findViewById(R.id.main_keyview);
            mMainView.setPreviewEnabled(false);   //这个是，效果图按住是出来的预览图。
            mMainView.setEnabled(true);
            mSwitchView = ((Activity) context).findViewById(R.id.action_keyview);
            mSwitchView.setPreviewEnabled(false);   //这个是，效果图按住是出来的预览图。
            mSwitchView.setEnabled(true);

            mMainView.setOnKeyboardActionListener(mListener);
            mSwitchView.setOnKeyboardActionListener(mListener);
        } catch (Exception ignored) {
        }
    }

    enum KEY_CODES {
        KEY_0(48, "0"),
        KEY_1(49, "1"),
        KEY_2(50, "2"),
        KEY_3(51, "3"),
        KEY_4(52, "4"),
        KEY_5(53, "5"),
        KEY_6(54, "6"),
        KEY_7(55, "7"),
        KEY_8(56, "8"),
        KEY_9(57, "9"),

        KEY_A(65, "A"),
        KEY_B(66, "B"),
        KEY_C(67, "C"),
        KEY_D(68, "D"),
        KEY_E(69, "E"),
        KEY_F(70, "F"),
        KEY_G(71, "G"),
        KEY_H(72, "H"),
        KEY_I(73, "I"),
        KEY_J(74, "J"),
        KEY_K(75, "K"),
        KEY_L(76, "L"),
        KEY_M(77, "M"),
        KEY_N(78, "N"),
        KEY_O(79, "O"),
        KEY_P(80, "P"),
        KEY_Q(81, "Q"),
        KEY_R(82, "R"),
        KEY_S(83, "S"),
        KEY_T(84, "T"),
        KEY_U(85, "U"),
        KEY_V(86, "V"),
        KEY_W(87, "W"),
        KEY_X(88, "X"),
        KEY_Y(89, "Y"),
        KEY_Z(90, "Z"),

        KEY_a(97, "a"),
        KEY_b(98, "b"),
        KEY_c(99, "c"),
        KEY_d(100, "d"),
        KEY_e(101, "e"),
        KEY_f(102, "f"),
        KEY_g(103, "g"),
        KEY_h(104, "h"),
        KEY_i(105, "i"),
        KEY_j(106, "j"),
        KEY_k(107, "k"),
        KEY_l(108, "l"),
        KEY_m(109, "m"),
        KEY_n(110, "n"),
        KEY_o(111, "o"),
        KEY_p(112, "p"),
        KEY_q(113, "q"),
        KEY_r(114, "r"),
        KEY_s(115, "s"),
        KEY_t(116, "t"),
        KEY_u(117, "u"),
        KEY_v(118, "v"),
        KEY_w(119, "w"),
        KEY_x(120, "x"),
        KEY_y(121, "y"),
        KEY_z(122, "z"),

        KEY_SYMBOLS_32(32, "space"),
        KEY_SYMBOLS_33(33, "!"),
        KEY_SYMBOLS_34(34, "\""),
        KEY_SYMBOLS_35(35, "#"),
        KEY_SYMBOLS_36(36, "$"),
        KEY_SYMBOLS_37(37, "%"),
        KEY_SYMBOLS_38(38, "&"),
        KEY_SYMBOLS_39(39, "'"),
        KEY_SYMBOLS_40(40, "("),
        KEY_SYMBOLS_41(41, ")"),
        KEY_SYMBOLS_42(42, "*"),
        KEY_SYMBOLS_43(43, "+"),
        KEY_SYMBOLS_44(44, ","),
        KEY_SYMBOLS_45(45, "-"),
        KEY_SYMBOLS_46(46, "."),
        KEY_SYMBOLS_47(47, "/"),

        KEY_SYMBOLS_58(58, ":"),
        KEY_SYMBOLS_59(59, ";"),
        KEY_SYMBOLS_60(60, "<"),
        KEY_SYMBOLS_61(61, "="),
        KEY_SYMBOLS_62(62, ">"),
        KEY_SYMBOLS_63(63, "?"),
        KEY_SYMBOLS_64(64, "@"),

        KEY_SYMBOLS_91(91, "["),
        KEY_SYMBOLS_92(92, "\\"),
        KEY_SYMBOLS_93(93, "]"),
        KEY_SYMBOLS_94(94, "^"),
        KEY_SYMBOLS_95(95, "_"),
        KEY_SYMBOLS_96(96, "`"),

        KEY_SYMBOLS_123(123, "{"),
        KEY_SYMBOLS_124(124, "|"),
        KEY_SYMBOLS_125(125, "}"),
        KEY_SYMBOLS_126(126, "~"),
        KEY_SYMBOLS_127(127, "del"),
        KEY_SYMBOLS_128(128, "€"),
        KEY_SYMBOLS_137(137, "‰"),
        KEY_SYMBOLS_163(163, "£"),
        KEY_SYMBOLS_165(165, "¥"),
        KEY_SYMBOLS_176(176, "°"),

        KEY_SYMBOLS_181(181, "¡"),
        KEY_SYMBOLS_182(182, "¿"),

        KEY_SYMBOLS_210(210, "×"),
        KEY_SYMBOLS_211(211, "÷"),

        KEY_SWITCH_shift_abc(-9000, ""),
        KEY_SWITCH_shift_ABC(-9001, ""),

        KEY_SWITCH_aA(-10001, "a/A"),
        KEY_SWITCH_123(-10002, "123"),
        KEY_SWITCH_SYMBOLS(-10003, "!?#"),

        KEY_SWITCH_CLOSE(-15000, "close"),

        KEY_END(-200000, "");

        private final int CODES;
        private final String LABEL;

        private int CODES() {
            return this.CODES;
        }
        private String LABEL() {
            return this.LABEL;
        }

        public static String getLabel(int code) {
            KEY_CODES[] keyCodes = values();
            for (KEY_CODES keyCode : keyCodes) {
                if (keyCode.CODES() == code) {
                    return keyCode.LABEL();
                }
            }
            return "";
        }

        KEY_CODES(int CODES, String LABEL) {
            this.CODES = CODES;
            this.LABEL = LABEL;
        }
    }

    private void switchKeyboard(int primaryCode) {
        Keyboard keyboard1 = null;
        Keyboard keyboard2 = null;
        if (primaryCode == KEY_CODES.KEY_SWITCH_CLOSE.CODES) {
            mEditText.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
            removeSKKeyboard();
            return;
        }
        if (primaryCode == KEY_CODES.KEY_SWITCH_shift_abc.CODES) {
            keyboard1 = new Keyboard(mContext, R.xml.sk_keyboard_abc);
            keyboard2 = new Keyboard(mContext, R.xml.sk_keyboard_switch_abc);
            isShiftLocked = false;
        } else if (primaryCode == KEY_CODES.KEY_SWITCH_shift_ABC.CODES) {
            keyboard1 = new Keyboard(mContext, R.xml.sk_keyboard_abc_shift);
            keyboard2 = new Keyboard(mContext, R.xml.sk_keyboard_switch_abc_shifted);
            isShiftLocked = true;
        } else if (primaryCode == KEY_CODES.KEY_SWITCH_aA.CODES) {
            int code = isShiftLocked ? KEY_CODES.KEY_SWITCH_shift_ABC.CODES : KEY_CODES.KEY_SWITCH_shift_abc.CODES;
            switchKeyboard(code);
            return;
        } else if (primaryCode == KEY_CODES.KEY_SWITCH_123.CODES) {
            keyboard1 = new Keyboard(mContext, R.xml.sk_keyboard_123);
            keyboard2 = new Keyboard(mContext, R.xml.sk_keyboard_switch_123);
        } else if (primaryCode == KEY_CODES.KEY_SWITCH_SYMBOLS.CODES) {
            keyboard1 = new Keyboard(mContext, R.xml.sk_keyboard_symbols);
            keyboard2 = new Keyboard(mContext, R.xml.sk_keyboard_switch_symbols);
        }
        if (keyboard1 != null) {
            mMainView.setKeyboard(keyboard1);
        }
        if (keyboard2 != null) {
            mSwitchView.setKeyboard(keyboard2);
        }
    }

    private void changeKeyboardStyle(int style) {
        if (style == EditorInfo.TYPE_CLASS_NUMBER) {
            switchKeyboard(KEY_CODES.KEY_SWITCH_123.CODES);
        } else {
            switchKeyboard(KEY_CODES.KEY_SWITCH_shift_abc.CODES);
            isShiftLocked = false;
        }
    }

    private void updateText(int primaryCode) {
        if (mEditText == null)
            return;
        int index = mEditText.getSelectionStart();
        Editable contentText = mEditText.getText();

        if (primaryCode == KEY_CODES.KEY_SYMBOLS_32.CODES) { //space
            contentText.insert(index, " ");
            mEditText.setText(contentText);
            if (mEditText.length() >= index+1) {
                mEditText.setSelection(index + 1);
            } else {
                mEditText.setSelection(index);
            }
        } else if (primaryCode == KEY_CODES.KEY_SYMBOLS_127.CODES) { //delete
            if(index == 0)
                return;
            contentText.delete(index - 1, index);
            mEditText.setText(contentText);
            mEditText.setSelection(index-1);
        } else {
            String content = KEY_CODES.getLabel(primaryCode);
            contentText.insert(index, content);
            mEditText.setText(contentText);
            if (mEditText.length() >= index+1) {
                mEditText.setSelection(index + 1);
            } else {
                mEditText.setSelection(index);
            }
        }
    }

    public void openSKKeyboard() {
        mKeyboardLayout.setVisibility(View.VISIBLE);
        mKeyboard_bottom.setVisibility(View.VISIBLE);
        mMainView.setVisibility(View.VISIBLE);
        mSwitchView.setVisibility(View.VISIBLE);
    }

    public void closeSKKeyboard() {
        mKeyboardLayout.setVisibility(View.GONE);
        mKeyboard_bottom.setVisibility(View.GONE);
        mMainView.setVisibility(View.GONE);
        mSwitchView.setVisibility(View.GONE);
    }

    public void removeSKKeyboard() {
        mEditText.clearFocus();
    }

    public void setSwitchViewVisibility(int status) {
        mKeyboard_bottom.setVisibility(status);
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                setSwitchViewVisibility(View.INVISIBLE);
                break;
            case MotionEvent.ACTION_UP:
                setSwitchViewVisibility(View.VISIBLE);
                break;
            default:
                break;
        }
        return false;
    }
}