import '../assets/keyboard.css';
import * as ReactDom from 'react-dom';
import { ViewController, React } from './ctr';
import { DelayCall } from 'somes/delay_call';
export class Keyboard extends ViewController {
    constructor() {
        super(...arguments);
        this.m_recipient = null;
        this._hasPresskeyCycle = false;
        this._handleContextMenu = (event) => {
            event.preventDefault();
        };
        this._hasPresskeyCycleSet = new DelayCall(() => {
            this._hasPresskeyCycle = false;
        }, 20);
        this._handleStart = () => {
            this._hasPresskeyCycle = true;
            this._hasPresskeyCycleSet.clear();
        };
        this._handleEnd = () => {
            this._hasPresskeyCycleSet.call();
        };
    }
    get isActive() {
        return !!this.m_recipient;
    }
    get recipient() {
        return this.m_recipient;
    }
    get hasPresskeyCycle() {
        return this._hasPresskeyCycle;
    }
    triggerInput(char) {
        if (this.recipient) {
            this.recipient._dom.value += char;
            this.recipient.triggerChange();
        }
    }
    triggerBackspace() {
        if (this.recipient) {
            var value = this.recipient._dom.value;
            this.recipient._dom.value = value.substr(0, value.length - 1);
            this.recipient.triggerChange();
        }
    }
    triggerDone() {
        if (this.recipient) {
            this.recipient.triggerDone();
        }
    }
    setRecipient(input) {
        if (input instanceof Input && this.m_recipient !== input) {
            if (this.m_recipient)
                this.m_recipient.blur();
            this.m_recipient = input;
            this.active(true);
        }
    }
    clearRecipient(input) {
        if (input === this.m_recipient) {
            input.blur();
            this.m_recipient = null;
            this.active(false);
        }
    }
    render() {
        return (React.createElement("div", { ref: "dom", onContextMenu: this._handleContextMenu, onTouchStart: this._handleStart, onTouchEnd: this._handleEnd, onTouchCancel: this._handleEnd, onMouseDown: this._handleStart, onMouseUp: this._handleEnd }, this.renderBody()));
    }
}
export class DefaultKeyboard extends Keyboard {
    constructor() {
        super(...arguments);
        this.state = { shift: 0, symbol: false, moreSymbol: false, active: false };
        this.m_shift = (e) => {
            e.stopPropagation();
            this.setState({ shift: (this.state.shift + 1) % 3 });
        };
        this.m_symbol = (e) => {
            e.stopPropagation();
            this.setState({ symbol: !this.state.symbol });
        };
        this.m_moreSymbol = (e) => {
            e.stopPropagation();
            this.setState({ moreSymbol: !this.state.moreSymbol });
        };
        this.m_space = (e) => {
            this.m_preventDefault(e);
            this.triggerInput(' ');
        };
        this.m_done = (e) => {
            this.m_preventDefault(e);
            this.triggerDone();
        };
        this.m_backspace = (e) => {
            this.m_preventDefault(e);
            this.triggerBackspace();
        };
        this.m_handle_input = (e) => {
            this.m_preventDefault(e);
            if (e.target.tagName.toUpperCase() == 'VIEW') {
                var { symbol, moreSymbol, shift } = this.state;
                if (symbol && moreSymbol) {
                    this.setState({ moreSymbol: false, symbol: false });
                }
                if (shift == 1) {
                    this.setState({ shift: 0 });
                }
                this.triggerInput(e.target.textContent);
            }
        };
    }
    char(char) {
        if (this.state.shift) {
            return char.toUpperCase();
        }
        else {
            return char;
        }
    }
    m_preventDefault(e) {
        e.stopPropagation();
    }
    active(action) {
        this.setState({ active: action });
    }
    renderMoreSymbol() {
        return (React.createElement("div", { className: "kb", onTouchStart: this.m_handle_input },
            React.createElement("div", { className: "row" },
                React.createElement("view", null, "["),
                React.createElement("view", null, "]"),
                React.createElement("view", null, '{'),
                React.createElement("view", null, '}'),
                React.createElement("view", null, "#"),
                React.createElement("view", null, "%"),
                React.createElement("view", null, "^"),
                React.createElement("view", null, "*"),
                React.createElement("view", null, "+"),
                React.createElement("view", null, "=")),
            React.createElement("div", { className: "row" },
                React.createElement("view", null, "\u02C7"),
                React.createElement("view", null, "\\"),
                React.createElement("view", null, "|"),
                React.createElement("view", null, '<'),
                React.createElement("view", null, '>'),
                React.createElement("view", null, "\u00A5"),
                React.createElement("view", null, "\u20AC"),
                React.createElement("view", null, "\u00A3"),
                React.createElement("view", null, "\u20A4"),
                React.createElement("view", null, "\u2022")),
            React.createElement("div", { className: "row" },
                React.createElement("view", { className: "grey", onTouchStart: this.m_moreSymbol }, "123"),
                React.createElement("view", null, "~"),
                React.createElement("view", null, ","),
                React.createElement("view", null, "\u2026"),
                React.createElement("view", null, "@"),
                React.createElement("view", null, "!"),
                React.createElement("view", null, "`"),
                React.createElement("view", { className: "grey", onTouchStart: this.m_backspace }, "backspace")),
            React.createElement("div", { className: "row" },
                React.createElement("view", { className: "grey", onTouchStart: this.m_symbol }, "return"),
                React.createElement("view", null, "."),
                React.createElement("view", { className: "space", onTouchStart: this.m_space }, "Space"),
                React.createElement("view", null, "?"),
                React.createElement("view", { className: "blue", onTouchStart: this.m_done }, "Done"))));
    }
    renderSymbol() {
        if (this.state.moreSymbol)
            return this.renderMoreSymbol();
        return (React.createElement("div", { className: "kb", onTouchStart: this.m_handle_input },
            React.createElement("div", { className: "row" },
                React.createElement("view", null, "1"),
                React.createElement("view", null, "2"),
                React.createElement("view", null, "3"),
                React.createElement("view", null, "4"),
                React.createElement("view", null, "5"),
                React.createElement("view", null, "6"),
                React.createElement("view", null, "7"),
                React.createElement("view", null, "8"),
                React.createElement("view", null, "9"),
                React.createElement("view", null, "0")),
            React.createElement("div", { className: "row" },
                React.createElement("view", null, "-"),
                React.createElement("view", null, "/"),
                React.createElement("view", null, ":"),
                React.createElement("view", null, ";"),
                React.createElement("view", null, "("),
                React.createElement("view", null, ")"),
                React.createElement("view", null, "_"),
                React.createElement("view", null, "$"),
                React.createElement("view", null, '&'),
                React.createElement("view", null, "\"")),
            React.createElement("div", { className: "row" },
                React.createElement("view", { className: "grey", onTouchStart: this.m_moreSymbol }, "more"),
                React.createElement("view", null, "~"),
                React.createElement("view", null, ","),
                React.createElement("view", null, "\u2026"),
                React.createElement("view", null, "@"),
                React.createElement("view", null, "!"),
                React.createElement("view", null, "'"),
                React.createElement("view", { className: "grey", onTouchStart: this.m_backspace }, "backspace")),
            React.createElement("div", { className: "row" },
                React.createElement("view", { className: "grey", onTouchStart: this.m_symbol }, "return"),
                React.createElement("view", null, "."),
                React.createElement("view", { className: "space", onTouchStart: this.m_space }, "Space"),
                React.createElement("view", null, "?"),
                React.createElement("view", { className: "blue", onTouchStart: this.m_done }, "Done"))));
    }
    renderBody() {
        if (!this.state.active)
            return null;
        if (this.state.symbol)
            return this.renderSymbol();
        var char = (e) => this.char(e);
        return (React.createElement("div", { className: "kb", onTouchStart: this.m_handle_input },
            React.createElement("div", { className: "row" },
                React.createElement("view", null, char('q')),
                React.createElement("view", null, char('w')),
                React.createElement("view", null, char('e')),
                React.createElement("view", null, char('r')),
                React.createElement("view", null, char('t')),
                React.createElement("view", null, char('y')),
                React.createElement("view", null, char('u')),
                React.createElement("view", null, char('i')),
                React.createElement("view", null, char('o')),
                React.createElement("view", null, char('p'))),
            React.createElement("div", { className: "row" },
                React.createElement("view", null, char('a')),
                React.createElement("view", null, char('s')),
                React.createElement("view", null, char('d')),
                React.createElement("view", null, char('f')),
                React.createElement("view", null, char('g')),
                React.createElement("view", null, char('h')),
                React.createElement("view", null, char('j')),
                React.createElement("view", null, char('k')),
                React.createElement("view", null, char('l'))),
            React.createElement("div", { className: "row" },
                React.createElement("view", { className: this.state.shift == 2 ? 'blue' : 'grey', onTouchStart: this.m_shift }, "shift"),
                React.createElement("view", null, char('z')),
                React.createElement("view", null, char('x')),
                React.createElement("view", null, char('c')),
                React.createElement("view", null, char('v')),
                React.createElement("view", null, char('b')),
                React.createElement("view", null, char('n')),
                React.createElement("view", null, char('m')),
                React.createElement("view", { className: "grey", onTouchStart: this.m_backspace }, "backspace")),
            React.createElement("div", { className: "row" },
                React.createElement("view", { className: "grey", onTouchStart: this.m_symbol }, "?123"),
                React.createElement("view", null, "."),
                React.createElement("view", { className: "space", onTouchStart: this.m_space }, "Space"),
                React.createElement("view", null, "?"),
                React.createElement("view", { className: "blue", onTouchStart: this.m_done }, "Done"))));
    }
}
var GlobalKeyboard = DefaultKeyboard;
var keyboard = null;
var panel = null;
function getPanel() {
    if (!panel) {
        panel = document.createElement('div');
        document.body.appendChild(panel);
    }
    return panel;
}
async function keyboardInstance() {
    if (!keyboard) {
        await new Promise(function (resolve, reject) {
            ReactDom.render(React.createElement(GlobalKeyboard, null), getPanel(), function () {
                keyboard = this;
                resolve();
            });
        });
    }
    return keyboard;
}
export function setGlobalKeyboard(keyboard) {
    if (GlobalKeyboard !== keyboard) {
        ReactDom.unmountComponentAtNode(getPanel());
        GlobalKeyboard = keyboard;
    }
}
export class Input extends ViewController {
    constructor() {
        super(...arguments);
        this._focus = false;
        this._handleChange = () => {
            this.triggerChange();
        };
        this._handleClick = () => {
            this._focusFun(true);
        };
        this._handleBlur = async (event) => {
            var keyboard = await keyboardInstance();
            if (keyboard.hasPresskeyCycle) {
            }
            else {
                this.blur();
            }
        };
    }
    triggerMounted() {
        if (this.props.initFocus) {
            setTimeout(e => {
                var input = this._dom;
                if (input)
                    input.focus();
            }, 100);
        }
    }
    triggerRemove() {
        keyboardInstance().then((k) => k.clearRecipient(this));
    }
    get value() {
        return this._dom.value;
    }
    set value(val) {
        this._dom.value = val;
    }
    get _dom() {
        return this.refs.input;
    }
    triggerChange() {
        if (this.props.onChange) {
            var input = this._dom;
            var len = input.value.length;
            setTimeout(() => {
                try {
                    input.focus();
                    input.setSelectionRange(len, len);
                }
                catch (err) { }
            }, 50);
            this.props.onChange();
        }
        setTimeout(() => this.refs.input.focus(), 5e2);
    }
    triggerDone() {
        if (this.props.onDone) {
            this.props.onDone();
        }
    }
    _focusFun(force = false) {
        if (force || !this._focus) {
            this._focus = true;
            keyboardInstance().then((k) => k.setRecipient(this));
            if (this.props.onFocus) {
                this.props.onFocus();
            }
            this.forceUpdate();
        }
    }
    async _blur() {
        if (this._focus) {
            var keyboard = await keyboardInstance();
            this._focus = false;
            keyboard.clearRecipient(this);
            if (this.props.onBlur) {
                this.props.onBlur();
            }
            this.forceUpdate();
        }
    }
    focus() {
        this._focusFun();
    }
    blur() {
        this._blur();
    }
    render() {
        var { value, className, type, style, placeholder, maxLength } = this.props;
        var focusCls = this._focus ? ' focus' : '';
        return (React.createElement("input", { maxLength: maxLength, placeholder: placeholder, className: className + focusCls, defaultValue: value, ref: "input", type: type, style: style, onChange: this._handleChange, onClick: this._handleClick, onFocus: () => this.focus(), onBlur: this._handleBlur }));
    }
}
