/*
 * 特别声明：本技术材料受《中华人民共和国著作权法》、《计算机软件保护条例》等法律、法规、行政
 * 规章以及有关国际条约的保护，赞同科技享有知识产权、保留一切权利并视其为技术秘密。未经本公司书
 * 面许可，任何人不得擅自（包括但不限于：以非法的方式复制、传播、展示、镜像、上载、下载）使用，
 * 不得向第三方泄露、透露、披露。否则，本公司将依法追究侵权者的法律责任。特此声明！
 *
 * Special Declaration: These technical material reserved as the technical secrets by AGREE
 * TECHNOLOGY have been protected by the "Copyright Law" "ordinances on Protection of Computer
 * Software" and other relevant administrative regulations and international treaties. Without
 * the written permission of the Company, no person may use (including but not limited to the
 * illegal copy, distribute, display, image, upload, and download) and disclose the above
 * technical documents to any third party. Otherwise, any infringer shall afford the legal
 * liability to the company.
 */
import {Composite} from "widget/Composite";
import {WidgetManager} from "util/WidgetManager";
import {EventHub} from "event/EventHub";
import {MessageType} from "event/MessageType";
import {Event as AdoreEvent} from "event/Event";
import {Keys} from "hotkey/Keys";
import {KeystrokeGenerator} from "hotkey/KeystrokeGenerator";
import {Layout} from "layout/Layout";
import {HeaderFooterLayoutData} from "layout/HeaderFooterLayoutData";
import {HeaderFooterLayout} from "layout/HeaderFooterLayout";
import {RowGridLayoutData} from "layout/RowGridLayoutData";
import {SideNavLayoutData} from "layout/SideNavLayoutData";
import {ADORE} from "ADORE";

/// <reference path="../typings/jquery.d.ts" />

export abstract class Widget {
    protected id: string;
    public parent: Composite;
    public $thisNode: JQuery;
    protected cssStyle: Object = {};
    protected enabled: boolean = true; // 默认可见
    protected visible: boolean = true; // 默认可用
    protected style: number;
    public layoutData: any;

    constructor(parentId: string, id: string, style: number) {
        this.id = id;
        this.style = style;
        WidgetManager.register(this);
        if (parentId) {
            this.parent = parentId ? WidgetManager.byId(parentId) : null;
            this.parent.addChild(this);
        }
    }

    public getId(): string {
        return this.id;
    }

    public sendFocusGain() {
        if (this.enabled) {
            EventHub.dispatchEvent(MessageType.WIDGET, { id: this.id, evtType: AdoreEvent.ON_FOCUS });
        }
    }

    public append() {
        if (this.parent) {
            this.$thisNode.appendTo(this.parent.$attachNode);
        } else {
            this.$thisNode.appendTo(document.body);
        }
    }

    public handleMouseDownEvent(e: MouseEvent) {
        EventHub.dispatchEvent(MessageType.WIDGET, {
            id: this.id,
            evtType: AdoreEvent.MOUSE_DOWN,
            button: e.button
        });
    }

    public handleMouseUpEvent(e: MouseEvent) {
        EventHub.dispatchEvent(MessageType.WIDGET, {
            id: this.id,
            evtType: AdoreEvent.MOUSE_UP,
            button: e.button
        });
    }

    public handleKeyDownEvent(e: KeyboardEvent, hasFilter: boolean) {
        let filter: boolean = false;
        let keyStroke = KeystrokeGenerator.generateKeyStroke(e);
        let keyEventObj = {
            id: this.id,
            evtType: AdoreEvent.KEY_DONW,
            altKey: e.altKey,
            shiftKey: e.shiftKey,
            ctrlKey: e.ctrlKey,
            keyCode: e.keyCode,
            keyStroke: keyStroke
        };
        if (e.keyCode === Keys.TAB) {
            e.preventDefault();
        }
        if (hasFilter) {
            filter = EventHub.dispatchEvent(MessageType.DISPLAY_FILTER, keyEventObj);
        }
        if (!filter) {
            EventHub.dispatchEvent(MessageType.WIDGET, keyEventObj);
        }else{
            // 过滤了就阻止事件进一步处理，并阻止事件冒泡
            e.preventDefault();
            e.stopPropagation();
        }
    }

    public handleKeyUpEvent(e: KeyboardEvent) {
        let keyStroke = KeystrokeGenerator.generateKeyStroke(e);
        let keyEventObj = {
            id: this.id,
            evtType: AdoreEvent.KEY_UP,
            altKey: e.altKey,
            shiftKey: e.shiftKey,
            ctrlKey: e.ctrlKey,
            keyCode: e.keyCode,
            keyStroke: keyStroke
        };
        EventHub.dispatchEvent(MessageType.WIDGET, keyEventObj);
    }

    public setEnabled(args: { enabled: boolean }) {
        this.enabled = args.enabled;
        if (this.enabled) {
            this.$thisNode.removeAttr("disabled");
        } else {
            this.$thisNode.attr("disabled", "disabled");
        }
    }

    public isEnabled(): boolean {
        return this.enabled;
    }

    public setVisible(args: { visible: boolean }) {
        this.visible = args.visible;
        if (this.visible) {
            this.css({ cssStyle: { "display": "block" } });
        } else {
            this.css({ cssStyle: { "display": "none" } });
        }
    }

    public isVisible(): boolean {
        return this.visible;
    }

    public dispose() {
        WidgetManager.unregister(this.id);
        this.$thisNode.remove();
        if (this.parent) {
            let index = this.parent.children.indexOf(this);
            this.parent.children.splice(index, 1);
        }
    }

    public setFocus(): void {
        // 空实现
    };

    public setLayoutData(args: { layoutData: any }) {
        let layout: any = this.parent ? this.parent.layout_ : undefined;
        if (layout) {
            let layoutData: any = args.layoutData;
            let layoutType = layout.toString();
            if (layoutType === "HeaderFooterLayout") {
                this.layoutData = new HeaderFooterLayoutData(layoutData);
            } else if (layoutType === "RowGridLayout") {
                this.layoutData = new RowGridLayoutData(layoutData);
            } else if (layoutType === "SideNavLayout") {
                this.layoutData = new SideNavLayoutData(layoutData);
            }
        }
    }

    public setBackgroundColor(attrs: {}) {

    }

    public css(args: { cssStyle: {} }) {
        if (this.$thisNode) {
            this.$thisNode.css(args.cssStyle);
        } else {
            this.cssStyle = $.extend(this.cssStyle, args.cssStyle);
        }
    }

    public toString(): string {
        return "Widget";
    }

    // 注意，本方法允许被调用多次，需要控制好资源创建和销毁！！！
    public postLayout() {
        if (this.cssStyle) {
            this.$thisNode.css(this.cssStyle);
            this.cssStyle = null;
        }
    }

    public initEvents(args: { events: Array<number> }) {
        let _this = this;
        setTimeout(function () {// TODO 先用延迟执行替代一下（因为setContentView后页面还未出现就可能执行这里的逻辑）
            if (!_this.$thisNode) {
                _this.$thisNode = $("#" + _this.id);
            }
            for (let i = 0; i < args.events.length; i++) {
                switch (args.events[i]) {
                    case AdoreEvent.CLICK:
                        _this.$thisNode.on("click", function (e: Event) {
                            EventHub.dispatchEvent(MessageType.WIDGET, { id: _this.id, evtType: AdoreEvent.CLICK });
                        });
                        break;
                    case AdoreEvent.MODIFY:
                        _this.$thisNode.on("input", function (e: Event) {
                            EventHub.dispatchEvent(MessageType.WIDGET, {
                                id: _this.id,
                                text: $(_this).val(),
                                evtType: AdoreEvent.MODIFY
                            });
                        });
                        break;
                    case AdoreEvent.ON_CHANGE:
                        // TODO
                        break;
                }
            }
        }, 800);
    }

}