/*
 * 特别声明：本技术材料受《中华人民共和国著作权法》、《计算机软件保护条例》等法律、法规、行政
 * 规章以及有关国际条约的保护，赞同科技享有知识产权、保留一切权利并视其为技术秘密。未经本公司书
 * 面许可，任何人不得擅自（包括但不限于：以非法的方式复制、传播、展示、镜像、上载、下载）使用，
 * 不得向第三方泄露、透露、披露。否则，本公司将依法追究侵权者的法律责任。特此声明！
 *
 * 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 {Widget} from "widget/Widget";
import {Composite} from "widget/Composite";
import {ADORE} from "ADORE";
import {EventHub} from "event/EventHub";
import {MessageType} from "event/MessageType";
import {Event} from "event/Event";

export class PatternLock extends Widget {

    private static Template = `<div class="modal adore_patternlock"></div>`;
    private options: IPasswordOptions;
    private arg: any;
    private count: number = 1;
    private gesturePwd: string;

    constructor(parentId: string, id: string, style: number) {
        super(parentId, id, style);
        this.$thisNode = $(PatternLock.Template).attr({ id: id });
    }

    public setOptions(args: { options: IPasswordOptions }) {
        this.options = args.options;
    }

    public setArgs(args: { arg: any }) {
        this.arg = args.arg;
    }

    public setCount(args: { count: number }) {
        this.count = args.count;
    }

    public layout() {
        this.append();
        this.$thisNode.GesturePasswd(this.options, this.arg);
    }

    public show() {
        let own = this;
        let oldPwd: string = "-1";
        let flag = true;
        let count1 = 0;
        this.$thisNode.on("hasPasswd", function (e, passwd) {
            //根据Count值比较,对比前值是否相同
            if (count1 === own.count - 1) {
                if (oldPwd === "-1") {
                    own.$thisNode.trigger("passwdRight");
                    EventHub.dispatchEvent(MessageType.WIDGET, { id: own.id, evtType: Event.ON_SLIDING, password: passwd });
                    own.$thisNode.closeModal();
                } else if (oldPwd !== passwd) {
                    own.$thisNode.trigger("passwdWrong");
                    EventHub.dispatchEvent(MessageType.WIDGET, { id: own.id, evtType: Event.ON_SLIDING, password: "-1" });
                    own.$thisNode.closeModal();
                } else {
                    own.$thisNode.trigger("passwdWrong");
                    EventHub.dispatchEvent(MessageType.WIDGET, { id: own.id, evtType: Event.ON_SLIDING, password: passwd });
                    own.$thisNode.closeModal();
                }
            } else if (count1 === 0) {
                own.$thisNode.trigger("passwdRight");
                oldPwd = passwd;
                count1 = count1 + 1;
            } else {
                if (oldPwd === passwd) {
                    own.$thisNode.trigger("passwdRight");
                    count1 = count1 + 1;
                } else {
                    own.$thisNode.trigger("passwdWrong");
                    EventHub.dispatchEvent(MessageType.WIDGET, { id: own.id, evtType: Event.ON_SLIDING, password: "-1" });
                    own.$thisNode.closeModal();
                }
            }
        });

        this.$thisNode.openModal({
            dismissible: false, // Modal can be dismissed by clicking outside of the modal
            opacity: .5, // Opacity of modal background
            in_duration: 300, // Transition in duration
            out_duration: 200, // Transition out duration
        });
    }

    public dispose() {
        $(".lean-overlay").remove();
        $("#" + this.id + "_lean_overlay").remove();
        super.dispose();
    }

}

export class GesturePasswd {

    private $element: JQuery;
    private options: IPasswordOptions;
    private pr: number;
    private rr: number;
    private o: number;
    private color: string;
    private id: string;
    private result: string;
    private pList: Point[];
    private sList: Point[];
    private tP: Point;
    private $c: HTMLCanvasElement;
    private $ctx: CanvasRenderingContext2D;
    private touched: boolean;
    private initImg: ImageData;

    constructor(element: JQuery, option?: IPasswordOptions, arg?: any) {
        this.$element = $(element);
        this.options = option;
        let that = this;
        this.pr = option.pointRadii;
        this.rr = option.roundRadii;
        this.o = option.space;
        this.color = option.color;

        //全局样式
        this.$element.css({
            "position": "relation",
            "width": this.options.width,
            "height": this.options.height,
            "background-color": option.backgroundColor,
            "overflow": "hidden",
            "cursor": "default"
        });

        //选择器规范
        if (!$(element).attr("id")) {
            $(element).attr("id", (Math.random() * 65535).toString());
        }

        this.id = "#" + $(element).attr("id");

        this.result = "";
        this.pList = [];
        this.sList = [];
        this.tP = new Point(0, 0);

        this.$element.append("<canvas class='main-c' width=" + this.options.width + " height=" + this.options.height + ">");
        this.$c = ($(this.id + " .main-c")[0] as HTMLCanvasElement);
        this.$ctx = this.$c.getContext("2d");

        this.initDraw();

        //用于判断点是否在大圆中

        this.touched = false;

        $(this.id).on("mousedown touchstart", { that: that }, function (e) {
            e.data.that.touched = true;
        });
        $(this.id).on("mouseup touchend", { that: that }, function (e) {
            e.data.that.touched = false;
            that.$ctx.clearRect(0, 0, that.options.width, that.options.height);
            that.$ctx.beginPath();
            that.$ctx.putImageData(e.data.that.initImg, 0, 0);
            that.allDraw(that.options.lineColor);
            // that.$ctx.stroke();
            for (let p in that.sList) {
                if (e.data.that.pointInList(that.sList[p], e.data.that.pList)) {
                    e.data.that.result = e.data.that.result + (e.data.that.pointInList(that.sList[p], e.data.that.pList)).toString();
                }
            }
            $(element).trigger("hasPasswd", that.result);
        });

        //
        $(this.id).on("touchmove mousemove", { that: that }, function (e: BaseJQueryEventObject) {
            if (e.data.that.touched) {
                let x = e.pageX || (e.originalEvent as TouchEvent).targetTouches[0].pageX;
                let y = e.pageY || (e.originalEvent as TouchEvent).targetTouches[0].pageY;
                x = x - that.$element.offset().left;
                y = y - that.$element.offset().top;
                let p = e.data.that.isIn(x, y);
                console.log(x);
                if (p !== 0) {
                    if (!e.data.that.pointInList(p, e.data.that.sList)) {
                        e.data.that.sList.push(p);
                    }
                }
                console.log(e.data.that.sList);
                e.data.that.draw(x, y);
            }

        });

        $(this.id).on("passwdWrong", { that: that }, function (e) {
            that.$ctx.clearRect(0, 0, that.options.width, that.options.height);
            that.$ctx.beginPath();
            that.$ctx.putImageData(that.initImg, 0, 0);
            that.allDraw("#cc1c21");
            that.result = "";
            that.pList = [];
            that.sList = [];

            setTimeout(function () {
                that.$ctx.clearRect(0, 0, that.options.width, that.options.height);
                that.$ctx.beginPath();
                that.initDraw();
            }, 500);

        });

        $(this.id).on("passwdRight", { that: that }, function (e) {
            that.$ctx.clearRect(0, 0, that.options.width, that.options.height);
            that.$ctx.beginPath();
            that.$ctx.putImageData(that.initImg, 0, 0);
            that.allDraw("#00a254");
            that.result = "";
            that.pList = [];
            that.sList = [];
            setTimeout(function () {
                that.$ctx.clearRect(0, 0, that.options.width, that.options.height);
                that.$ctx.beginPath();
                that.initDraw();
            }, 500);
        });

    }

    static PatternLockDefaultOptions: IPasswordOptions = {
        zindex: 100,
        roundRadii: 25,
        pointRadii: 6,
        space: 30,
        width: 240,
        height: 240,
        lineColor: "#00aec7",
        backgroundColor: "#252736",
        color: "#FFFFFF"
    };

    private initDraw() {
        this.$ctx.strokeStyle = this.color; //边框样式
        this.$ctx.lineWidth = 2;
        for (let j = 0; j < 3; j++) {
            for (let i = 0; i < 3; i++) {
                this.$ctx.moveTo(this.o / 2 + this.rr * 2 + i * (this.o + 2 * this.rr), this.o / 2 + this.rr + j * (this.o + 2 * this.rr)); //绘制线段
                //this.$ctx.beginPath();
                this.$ctx.arc(this.o / 2 + this.rr + i * (this.o + 2 * this.rr), this.o / 2 + this.rr + j * (this.o + 2 * this.rr), this.rr, 0, 2 * Math.PI); //绘制圆弧
                //this.$ctx.closePath();

                let tem = new Point(this.o / 2 + this.rr + i * (this.o + 2 * this.rr), this.o / 2 + this.rr + j * (this.o + 2 * this.rr)); //创建Point
                if (this.pList.length < 9)
                    this.pList.push(tem);
            }
        }
        this.$ctx.stroke(); //canvas元素绘制图像的时候有两种方法,绘制边框
        this.initImg = this.$ctx.getImageData(0, 0, this.options.width, this.options.height);
    }

    private isIn(x: number, y: number): Point | number {
        for (let p in this.pList) {
            if ((Math.pow((x - this.pList[p]["x"]), 2) + Math.pow((y - this.pList[p]["y"]), 2)) < Math.pow(this.rr, 2)) {
                return this.pList[p];
            }
        }
        return 0;
    }

    private pointDraw(c?: string) {
        if (arguments.length > 0) {
            this.$ctx.strokeStyle = c;
            this.$ctx.fillStyle = c;
        }
        for (let p in this.sList) {
            this.$ctx.moveTo(this.sList[p]["x"] + this.pr, this.sList[p]["y"]);
            this.$ctx.arc(this.sList[p]["x"], this.sList[p]["y"], this.pr, 0, 2 * Math.PI);
            this.$ctx.fill();
        }
    }

    private lineDraw(c?: string) {
        if (arguments.length > 0) {
            this.$ctx.strokeStyle = c;
            this.$ctx.fillStyle = c;
        }
        if (this.sList.length > 0) {
            for (let p in this.sList) {
                if (p === "0") {
                    console.log(this.sList[p]["x"], this.sList[p]["y"]);
                    this.$ctx.moveTo(this.sList[p]["x"], this.sList[p]["y"]);
                    continue;
                }
                this.$ctx.lineTo(this.sList[p]["x"], this.sList[p]["y"]);
                console.log(this.sList[p]["x"], this.sList[p]["y"]);
            }

        }
    }

    private allDraw(c: string) {
        if (arguments.length > 0) {
            this.pointDraw(c);
            this.lineDraw(c);
            this.$ctx.stroke();
        }
        else {
            this.pointDraw();
            this.lineDraw();
        }

    };

    private draw(x: number, y: number) {
        this.$ctx.clearRect(0, 0, this.options.width, this.options.height);
        this.$ctx.beginPath();
        //that.initDraw();
        this.$ctx.putImageData(this.initImg, 0, 0);
        this.$ctx.lineWidth = 4;
        this.pointDraw(this.options.lineColor);
        this.lineDraw(this.options.lineColor);
        this.$ctx.lineTo(x, y);
        this.$ctx.stroke();
    }

    private pointInList(poi: Point, list: Point[]): number | boolean {
        for (let p in list) {
            if (poi["x"] === list[p]["x"] && poi["y"] === list[p]["y"]) {
                let i = parseInt(p);
                return ++i;
            }
        }
        return false;
    }
}

export class Point {
    public x: number;
    public y: number;
    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }
}

;
(function ($: any) {

    function Plugin(option?: IPasswordOptions, arg?: any) {
        this.each(function () {
            let $this = $(this);
            let options = $.extend({}, GesturePasswd.PatternLockDefaultOptions, typeof option === "object" && option);
            let data: any = $this.data("GesturePasswd");
            let action: any = typeof option === "string" ? option : NaN;
            if (!data) $this.data("danmu", (data = new GesturePasswd(this, options)));
            if (action) data[action](arg);
        });
    }

    $.fn.GesturePasswd = Plugin;

})(jQuery);
