
import {Widget} from "widget/Widget";
import {EventHub} from "event/EventHub";
import {MessageType} from "event/MessageType";
import {Event} from "event/Event";
import {Keys} from "hotkey/Keys";
import {Table} from "widget/table/Table";
import {TableColumn} from "widget/table/TableColumn";
import {TableConstants} from "widget/table/TableConstants";


export class TableItem extends Widget {

    // 表格行标记
    private static TemplateTr = `<tr></tr>`;
    // cellType:NONE(默认cellType) 
    private static TemplateNone = `<td></td>`;
    // cellType:TEXT
    private static TemplateText = `
        <td>
            <input type="text" style="border: none;text-align: inherit;width: 100%;font-size: 1rem;"/>
        </td>`;
    // cellType:Check
    private static TemplateCheck = `
        <td>
            <p tabindex="-1">
                <input type="checkbox" id="" class="filled-in"/>
                <label for="" style="margin-top: 9px"></label>
            </p>
        </td>`;
    // cellType:COMBO
    private static TemplateCombo = `
        <td>
            <select class="browser-default" style="display:inline;width: 100%;height:36px;">
            </select>
        </td>`;
    // cellType:BUTTON
    private static TemplateButton = `
        <td>
            <div class="waves-effect waves-light btn adore_button" style="background: #17D1C8;" tabindex="-1" data-position="top" data-delay="50"><span></span><i></i></div>
        </td>`;
    // select option
    private static TemplateOption = `<option></option>`;


    private $attachNode: JQuery;

    private isComboFocus: boolean = false;
    private isTextFocus: boolean = false;
    private rowIndex: number = -1;


    /**
     * templates数组:
     *  0:行标记  1:cellType--NONE 2:cellType--TEXT 3:cellType--CHECK 4:cellType--COMBO 5:select option
     */
    constructor(parentId: string, id: string, style: number) {
        super(parentId, id, style);
        this.$thisNode = $(TableItem.TemplateTr).attr("id", this.id);
        this.$attachNode = this.$thisNode;
        let tableId = this.parent.getId();
        let itemId = this.id;
        let own = this;

        // 添加click事件
        this.$thisNode.on("click", function (e) {
            // 过滤行已选中并再次点击选中事件
            let preTr = $("#" + tableId).find("tr[hadSelected]");
            if (preTr.length > 0 && preTr[0] === e.currentTarget) {
                return;
            }
            // 过滤th
            let th = $(this).find("th");
            if (th.length > 0) {
                return;
            }
            preTr.removeClass("adore_table_item_selected")
            preTr.removeAttr("hadSelected");
            $(this).addClass("adore_table_item_selected");
            $(this).attr("hadSelected", "true");
            // 发送onclick事件
            EventHub.dispatchEvent(MessageType.WIDGET, {
                id: tableId,
                itemId: itemId,
                evtType: Event.CLICK
            });
        });

    }

    public setDatas(args: { datas: string[] }) {
        let itemId = this.id;
        let datas = args.datas;
        let columns = (<Table>this.parent).columns;
        let i: number, j: number, data: string, tdNode: JQuery, id: string, comboNode: JQuery, optionNode: JQuery, cellText: string;
        this.$thisNode.find("td").html("<div style='display:none;'></div>");//把注释内容也清理
        this.$thisNode.find("td").remove();
        // 清楚掉tdNodeArray
        this.tdNodeArray.splice(0,this.tdNodeArray.length);
        let own = this;
        // 添加数据
        this.addCellRowNum();
        for (i = 0; i < columns.length; i++) {
            this.addCell(i, datas[i]);
        }
    }

    public sendFocusGain() {
        let id = this.parent.getId;
        EventHub.dispatchEvent(MessageType.WIDGET, { id: id, evtType: Event.ON_FOCUS });
    }


    public append() {
        if (this.parent) {
            if ((<Table>this.parent).$tBody) {
                if (this.rowIndex >= 0 && this.rowIndex < ((<Table>this.parent).items.length - 1)) {
                    var index = (<Table>this.parent).items.indexOf(this);
                    (<Table>this.parent).items.splice(index, 1);
                    this.$attachNode.insertBefore((<TableItem>(<Table>this.parent).items[this.rowIndex]).$attachNode.eq(0));
                    (<Table>this.parent).items.splice(this.rowIndex, 0, this);
                    (<Table>this.parent).refreshCellRowNum();
                    // 只对第一次生效
                    this.rowIndex = -1;
                } else {
                    this.$thisNode.appendTo((<Table>this.parent).$tBody);
                }
            } else {
                this.$thisNode.appendTo((<Table>this.parent).$attachNode);
            }
        } else {
            this.$thisNode.appendTo(document.body);
        }
    }

    public layout() {
        this.append();
    }

    public clearSelection() {
        this.$thisNode.removeClass("adore_table_item_selected")
        this.$thisNode.removeAttr("hadSelected");
    }

    public setSelection() {
        this.$thisNode.addClass("adore_table_item_selected");
        this.$thisNode.attr("hadSelected", "true");
    }

    public setColor(args: { color: string }) {
        this.$thisNode.css("color", args.color);
    }

    public setEnabled(args: {}) {
        //由TableColumn控制
    }

    public setVisible(args: {}) {
        //由TableColumn控制
    }

    public dispose() {
        super.dispose();
        if (this.parent) {
            let index = (<Table>this.parent).items.indexOf(this);
            (<Table>this.parent).items.splice(index, 1);
            // 如果有序号列，那table需要刷新下序号列
            if ((<Table>this.parent).containRowNum) {
                (<TableColumn>(<Table>this.parent).rowNumCol).refreshRowNumCol(index);
            }
        }
    }

    public handleKeyDownEvent(e: KeyboardEvent, hasFilter: boolean) {
        if (e.keyCode == Keys.RIGHT_ARROW || e.keyCode == Keys.LEFT_ARROW) {
            if (!this.isTextFocus) { //如果焦点在Text中，不拦截默认事件
                e.preventDefault(); //拦截默认事件
                this.parent.handleKeyDownEvent(e, hasFilter);
            } else if (this.isComboFocus) { //如果光标在COMBO中，拦截默认事件
                e.preventDefault();
                this.parent.handleKeyDownEvent(e, hasFilter);
            }
        } else if (e.keyCode == Keys.UP_ARROW || e.keyCode == Keys.DOWN_ARROW) {
            if (this.isComboFocus) {
                e.preventDefault();
                this.parent.handleKeyDownEvent(e, hasFilter);
            } else {
                this.parent.handleKeyDownEvent(e, hasFilter);
            }
        } else {
            this.parent.handleKeyDownEvent(e, hasFilter);
        }
    }

    public setCellSelection(args: { colIndex: number }) {
        let colIndex = args.colIndex; //利用列号得到
        let type = (<Table>this.parent).columns[colIndex].type;
        let $tdNode = this.tdNodeArray[colIndex];
        switch (type) {
            case TableConstants.CELL_TYPE_TEXT:
                if (document.activeElement !== $tdNode.find("input")[0]) {
                    $tdNode.find("input").focus();
                }
                break;
            case TableConstants.CELL_TYPE_COMBO:
                if (document.activeElement !== $tdNode.find("select")[0]) {
                    $tdNode.find("select").focus();
                }
                break;
            case TableConstants.CELL_TYPE_CHECK:
                if (document.activeElement !== $tdNode.find("p")[0]) {
                    $tdNode.find("p").focus();
                }
                break;
            case TableConstants.CELL_TYPE_BUTTON:
                if (document.activeElement !== $tdNode.find("a")[0]) {
                    $tdNode.find("div").focus();
                }
                break;
            default:
                break;
        }
    }

    public setCheckValue(args: { colIndex: number }) { //获取CHECK的值，再获取其相反值
        let colIndex = args.colIndex;
        let $checkNode = this.tdNodeArray[colIndex].find("input");
        let value = $checkNode.prop("checked");
        $checkNode.prop("checked", !value);
    }

    public openSelect(args: { colIndex: number }) {
        let colIndex = args.colIndex;
        let elem = this.tdNodeArray[colIndex].find("select");
        if (document.createEvent) {
            let e = document.createEvent("MouseEvents");
            e.initMouseEvent("mousedown");
            elem[0].dispatchEvent(e);
        } else if (elem[0].fireEvent) {
            elem[0].fireEvent("onmousedown");
        }
    }

    public setFocus() {
        // do nothing now
    }


    public tdNodeArray = new Array();

    public setCheckboxState(index: number, checkboxState: boolean) {
        let $checkboxNode = this.tdNodeArray[index];
        $checkboxNode.find("input:checkbox").eq(0).prop("checked", checkboxState);
        $checkboxNode.find("input:checkbox").eq(0).prop("indeterminate", false);
    }

    public refreshHeadCheckboxState(index: number) {
        let $checkboxNode = this.tdNodeArray[index];
        let currentChecked = $checkboxNode.find("input").eq(0).prop("checked");
        let column: TableColumn = (<Table>this.parent).columns[index];
        let $headCheckNode = column.$thisNode.find("input").eq(0);
        let size = (<Table>this.parent).items.length;
        let state = -1;
        for (let i = 0; i < size; i++) {
            let tmpChecked = (<TableItem>(<Table>this.parent).items[i]).getCheckboxState(index);
            if (tmpChecked) {
                if (state == -1) {
                    state = 0;
                } else if (state != 0) {
                    state = 2;
                    break;
                }
            } else {
                if (state == -1) {
                    state = 1;
                } else if (state != 1) {
                    state = 2;
                    break;
                }
            }
        }
        if (state == 0) {
            $headCheckNode.prop("checked", true);
            $headCheckNode.prop("indeterminate", false);
        } else if (state == 1) {
            $headCheckNode.prop("checked", false);
            $headCheckNode.prop("indeterminate", false);
        } else {
            $headCheckNode.prop("checked", false);
            $headCheckNode.prop("indeterminate", true);
        }
    }

    public getCheckboxState(index: number) {
        let $checkboxNode = this.tdNodeArray[index];
        return $checkboxNode.find("input").eq(0).prop("checked");
    }

    private $rowNumNode: JQuery;
    public addCellRowNum() {
        if ((<Table>this.parent).containRowNum) {
            // let index = this.father.items.indexOf(this);
            // datas.unshift((index+1) + "");
            let index = (<Table>this.parent).items.indexOf(this);
            //NONE
            let $tdNode = $(TableItem.TemplateNone);
            $tdNode.attr("title", (index + 1) + "");
            $tdNode.text((index + 1) + "");
            $tdNode.appendTo(this.$attachNode);
            $tdNode.css("text-align", "center");
            this.$rowNumNode = $tdNode;
        }
    }

    public refreshCellRowNum(index: number) {
        if ((<Table>this.parent).containRowNum) {
            if (this.$rowNumNode) {
                this.$rowNumNode.text((index + 1) + "");
            }
        }
    }

    public addCell(colIndex: number, data: string) {
        let columns = (<Table>this.parent).columns;
        let $tdNode: JQuery, $comboNode: JQuery, $optionNode: JQuery, id: string, cellText: string;
        let own = this;
        let itemId = this.id;
        let tableId = this.parent.getId();
        let i = colIndex;
        cellText = TableConstants.CELL_TYPE_NULL;
        //NONE
        if (columns[i].type === TableConstants.CELL_TYPE_NULL) {
            $tdNode = $(TableItem.TemplateNone);
            $tdNode.attr("title", data);
            $tdNode.text(data);
        }
        // TEXT
        else if (columns[i].type === TableConstants.CELL_TYPE_TEXT) {
            $tdNode = $(TableItem.TemplateText); 
            $tdNode.find("input").val(data);
            cellText = "input";
            $tdNode.find("input").attr("col", i).on("input", function (e) {
                EventHub.dispatchEvent(MessageType.WIDGET, {
                    id: itemId,
                    col: own.getColIndex($tdNode),
                    data: this.value,
                    evtType: Event.MODIFY
                });
            }).on("focus", function (e) {
                console.log("focus in : TEXT");
                own.isTextFocus = true;
                (<Table>own.parent).isCellFocus = true;
                (<Table>own.parent).sendFocusGain();
                EventHub.dispatchEvent(MessageType.WIDGET, {
                    id: tableId,
                    itemId: itemId,
                    col: own.getColIndex($tdNode), //获取列号
                    evtType: Event.CLICK
                });
            }).on("blur", function () {
                console.log("focus out : TEXT");
                own.isTextFocus = false;
                (<Table>own.parent).isCellFocus = false;
            });
        }
        //CHECK
        else if (columns[i].type === TableConstants.CELL_TYPE_CHECK) {
            $tdNode = $(TableItem.TemplateCheck);
            id = columns[i].id + "_" + this.id;
            $tdNode.find("input").attr("id", id);
            $tdNode.find("label").attr("for", id);
            cellText = "input";
            if (data === "true") {
                $tdNode.find("input").prop("checked", true);
            }
            $tdNode.find("input").attr("col", i).on("change", function (e) {
                EventHub.dispatchEvent(MessageType.WIDGET, {
                    id: itemId,
                    col: own.getColIndex($tdNode),
                    data: this.checked + "",
                    evtType: Event.MODIFY
                });
            });
            $tdNode.find("input").attr("col", i).on("click", function (e) {
                let colIndex = own.getColIndex($tdNode);
                own.refreshHeadCheckboxState(parseInt(colIndex));
            });
            $tdNode.find("p").on("focus", function (e) {
                console.log("focus in : CHECK");
                (<Table>own.parent).isCellFocus = true;
                (<Table>own.parent).sendFocusGain();
                EventHub.dispatchEvent(MessageType.WIDGET, {
                    id: tableId,
                    itemId: itemId,
                    col: own.getColIndex($tdNode), //获取列号
                    evtType: Event.CLICK
                });
            }).on("blur", function () {
                (<Table>own.parent).isCellFocus = false;
            });
        }
        // COMBO
        else if (columns[i].type === TableConstants.CELL_TYPE_COMBO) {
            $tdNode = $(TableItem.TemplateCombo);
            cellText = "select";
            if (columns[i].options) {
                $comboNode = $tdNode.find("select");
                for (let j = 0; j < columns[i].options.length; j++) {
                    $optionNode = $(TableItem.TemplateOption).text(columns[i].options[j]);
                    if (columns[i].options[j] === data) {
                        $optionNode.prop("selected", true);
                    }
                    $optionNode.appendTo($comboNode);
                }
                $comboNode.attr("col", i + "").on("change", function (e) {
                    EventHub.dispatchEvent(MessageType.WIDGET, {
                        id: itemId,
                        col: own.getColIndex($tdNode),
                        data: this.value,
                        evtType: Event.MODIFY
                    });
                }).on("focus", function (e) {
                    console.log("focus in : COMBO");
                    (<Table>own.parent).isCellFocus = true;
                    own.isComboFocus = true;
                    (<Table>own.parent).sendFocusGain();
                    EventHub.dispatchEvent(MessageType.WIDGET, {
                        id: tableId,
                        itemId: itemId,
                        col: own.getColIndex($tdNode), //获取列号
                        evtType: Event.CLICK
                    });
                }).on("blur", function (e) {
                    console.log("focus out : COMBO");
                    own.isComboFocus = false;
                    (<Table>own.parent).isCellFocus = false;
                });

                $comboNode.on("click mousedown", function () {
                    (<Table>own.parent).isCellFocus = true;
                    own.isComboFocus = true;
                    EventHub.dispatchEvent(MessageType.WIDGET, {
                        id: tableId,
                        itemId: itemId,
                        col: own.getColIndex($tdNode), //获取列号
                        evtType: Event.CLICK
                    });
                });
            }
        }
        // BUTTON
        else if (columns[i].type === TableConstants.CELL_TYPE_BUTTON) {
            $tdNode = $(TableItem.TemplateButton);
            let begin = data.indexOf("${");
            let end = data.indexOf("}");
            cellText = "a";
            if (begin !== -1 && end > begin) {
                let clazz = data.substring(begin + 2, end);
                if (clazz.indexOf("-") !== -1) {
                    $tdNode.find("span").addClass(clazz);
                } else {
                    $tdNode.find("span").addClass("adr-" + clazz);
                }
            } else {
                $tdNode.find("span").text(data);
            }
            $tdNode.find("div").attr("col", i + "").on("click", function (e) {
                EventHub.dispatchEvent(MessageType.WIDGET, {
                    id: itemId,
                    col: own.getColIndex($tdNode),
                    data: data,
                    evtType: Event.MODIFY
                });
            }).on("focus", function (e) {
                (<Table>own.parent).isCellFocus = true;
                (<Table>own.parent).sendFocusGain();
                EventHub.dispatchEvent(MessageType.WIDGET, {
                    id: tableId,
                    itemId: itemId,
                    col: own.getColIndex($tdNode), //获取列号
                    evtType: Event.CLICK
                });
            }).on("blur", function () {
                (<Table>own.parent).isCellFocus = false;
            })
        }
        if (colIndex < this.tdNodeArray.length) {
            let $tempNode = this.tdNodeArray[colIndex];
            $tdNode.insertBefore($tempNode.eq(0));
            this.tdNodeArray.splice(colIndex, 0, $tdNode);
        } else {
            $tdNode.appendTo(this.$attachNode);
            this.tdNodeArray.push($tdNode);
        }
        if (columns[i].type === TableConstants.CELL_TYPE_CHECK) {
            this.refreshHeadCheckboxState(i);
        }
        if (columns[i].visible === false) {
            $tdNode.css("display", "none");
        }
        if (columns[i].enabled === false && cellText !== TableConstants.CELL_TYPE_NULL) {
            $tdNode.find(cellText).attr("disabled", "disabled");
        }
        if (columns[i].alignmentContent) {
            $tdNode.css("text-align", columns[i].alignmentContent);
        }
    }

    public getColIndex(tdNode: JQuery) {
        return this.tdNodeArray.indexOf(tdNode) + "";
    }

    public setRowIndex(args: { rowIndex: number }) {
        this.rowIndex = args.rowIndex;
    }

}
