"use strict";
import {MyRecovery} from "../model/MyRecovery.js";
import {MyDocItem} from "../model/MyDocItem.js";
import {MyMapItem} from "../model/MyMapItem.js";


export class MyBiz {

    constructor() {
    }

    /**
     * 根据类型名称解析 样式的 class 名称
     * @param styleName
     * @returns {string}
     */
    parseStyleName2ClassName(styleName) {
        switch (styleName) {
            case "b":
                return "childStyleStrong";
            case "i":
                return "childStyleI";
            case "u":
                return "childStyleU";
            case "c_red":
                return "childStyleColor";
            case "del":
                return "childStyleDel"
        }
    }

    /**
     * 输入事件
     * @param e
     */
    inputHandle(e) {
        let curP = window.myEdit.utils.GetEventTarget(e);
        this.updateText(curP)
    }

    /**
     * 中文输入开始事件
     * @param e
     */
    compositionstartHandle(e) {
        // console.log("compositionstart")
        window.myEdit.ctx.inCompositionEvent = true
    }

    /**
     * 中文输入结束事件
     * @param e
     */
    compositionendHandle(e) {
        // console.log("compositionend")
        let curP = window.myEdit.utils.GetEventTarget(e);
        this.updateText(curP)
        //中文输入结束
        window.myEdit.ctx.inCompositionEvent = false
    }


    /**
     * 撤销事件
     * @param event
     */
    cancelHandle(event) {
        console.log('触发ctrl + Z 事件', event.target)
        if (window.myEdit.ctx.latestOpDoc !== undefined && window.myEdit.ctx.latestOpDoc !== null) {
            //恢复
            window.myEdit.ctx.latestOpDoc.recovery();
            //测试展示
            window.myEdit.ctx.showTestText()
            //阻止事件
            window.myEdit.utils.ProhibitDefaultEvent(event);
        }

        window.myEdit.ctx.latestOpDoc = null
    }

    /**
     * 删除事件
     * @param event
     */
    deleteHandle(event) {
        let curP = window.myEdit.utils.GetEventTarget(event);
        let cNo = parseInt(curP.getAttribute("data-order"))

        //维护最近一次编辑的内容
        if (window.myEdit.ctx.latestOpDoc === undefined
            || window.myEdit.ctx.latestOpDoc === null
            || window.myEdit.ctx.latestOpDoc.getData().getAttribute("data-id") !== curP.getAttribute("data-id")) {
            window.myEdit.ctx.latestOpDoc = new MyRecovery(curP.cloneNode(true), function () {
                let cNo = parseInt(this.data.getAttribute("data-order"))
                console.log("恢复", this.data, cNo, "  this: ", this)
                if (cNo > 1) {
                    window.myEdit.utils.InsertAfter(this.data, document.querySelector("#noteshare p[data-order='" + (cNo - 1) + "']"))
                } else {
                    //添加元素到首位 todo_xxx
                    // window.myEdit.ctx.MyRoot.insertBefore(this.data, window.myEdit.ctx.MyRoot.children[0])
                    window.myEdit.ctx.MyRoot.insertBefore(this.data, window.myEdit.ctx.MyRoot.children[0]);
                }

                // 恢复该元素展示
                window.myEdit.ctx.MyDocMap.get(cNo).setHidden(false);
            })
        }


        //如果是第一行
        let previousSibling = curP.previousSibling
        // console.log(curP, previousSibling === undefined, previousSibling.id === undefined)
        if (previousSibling === undefined || previousSibling.id === undefined) {
            //显示用户的输入内容
            window.myEdit.ctx.showTestText()
            return
        }


        console.log('触发删除', curP.innerHTML, cNo)
        let curS = window.myEdit.utils.GetSelection();
        // console.log("当前内容: ", curP.innerHTML, " 当前选区 :", curS)
        //处理前面没有内容,后面还有内容需要拼接到上层的场景
        if ((curS.isCollapsed && curS.anchorOffset === 0) || curP.innerHTML === '<br>') {
            let curNodeRetainHtml = curP.innerHTML
            //阻止事件传递
            window.myEdit.utils.ProhibitDefaultEvent(event);
            //设置该元素隐藏
            window.myEdit.ctx.MyDocMap.get(cNo).setHidden(true)
            //删除当前元素
            // curP.remove()
            curP.innerHTML = "<br/>"
            let emptyRowNoList = window.myEdit.ctx.MyDocMap.get("emptyRowNoList");
            if (emptyRowNoList === undefined || emptyRowNoList === null) {
                emptyRowNoList = [];
                window.myEdit.ctx.MyDocMap.set("emptyRowNoList", emptyRowNoList);
            }
            emptyRowNoList.push(cNo);
            //拼接
            if (curNodeRetainHtml !== '<br>') {
                previousSibling.innerHTML = previousSibling.innerHTML + curNodeRetainHtml
            }

            //收起选区到一个点,光标落在一个可编辑元素上
            console.log("previousSibling: ",previousSibling);
            window.getSelection().setPosition(previousSibling, 1);
        }

        //显示用户的输入内容
        window.myEdit.ctx.showTestText();
    }

    /**
     * 回车事件
     * @param event
     * @param onkeydownHandle
     */
    enterHandler(event) {
        //阻止事件
        window.myEdit.utils.ProhibitDefaultEvent(event);
        //uuid
        let uuid = window.myEdit.utils.Uuid();
        //rowNo
        let rowNo = 0;
        let emptyRowNoList = window.myEdit.ctx.MyDocMap.get("emptyRowNoList");
        // console.log(emptyRowNoList);
        let empListIsEmpty = (emptyRowNoList === undefined || emptyRowNoList === null || emptyRowNoList.length <= 0);
        if (!empListIsEmpty) {
            let tmpArr = [];
            for (let i = 0; i < emptyRowNoList.length; i++) {
                let tmpNo = emptyRowNoList[i];
                if (window.myEdit.ctx.getMapItem(tmpNo).getHidden()) {
                    tmpArr.push(emptyRowNoList[i]);
                }
            }
            window.myEdit.ctx.MyDocMap.set("emptyRowNoList", tmpArr);
            empListIsEmpty = tmpArr.length <= 0;
            emptyRowNoList = tmpArr
        }

        if (empListIsEmpty) {
            rowNo = window.myEdit.ctx.incrementNumThenReturn();
            //添加新元素
            let newParagraph = document.createElement("p")
            newParagraph.setAttribute("contenteditable", "true")
            newParagraph.setAttribute("data-id", uuid)
            newParagraph.setAttribute("id", uuid)
            newParagraph.setAttribute("data-order", rowNo)
            newParagraph.onkeyup = window.myEdit.eventListener.KeydownListener
            newParagraph.innerHTML = "<br>"
            window.myEdit.ctx.MyRoot.appendChild(newParagraph)
            window.myEdit.ctx.MyDocMap.set(rowNo, new MyMapItem(uuid))

            //收起选区到一个点,光标落在一个可编辑元素上
            window.getSelection().setPosition(newParagraph, 0);
            return
        }

        let sortArr = emptyRowNoList.sort((a, b) => a - b)
        console.log(sortArr);
        // 最小值
        rowNo = sortArr[0];
        let newParagraph = document.querySelector("#noteshare p[data-order='" + rowNo + "']");
        newParagraph.innerHTML = "<br>";
        window.myEdit.ctx.MyDocMap.get(rowNo).setHidden(false);
        //收起选区到一个点,光标落在一个可编辑元素上
        window.getSelection().setPosition(newParagraph, 0)
    }


    /**
     * 更新文档
     * @param {*} curP
     */
    updateText(curP) {
        if (window.myEdit.ctx.inCompositionEvent) {
            return;
        }

        let myP = new MyDocItem(curP);
        let cNo = myP.parseOrder();
        let mapItem = window.myEdit.ctx.getMapItem(cNo)

        //内容不变则不处理
        let h5CurLen = curP.innerText.length
        let myDocNodeLen = (mapItem && mapItem.getSource()) ? mapItem.getSource().length : 0
        if (h5CurLen === myDocNodeLen) {
            return
        }

        mapItem.setSource(curP.innerText);
        mapItem.setHidden(false);
        // console.log("curPTx: ", curP.innerText, "MyDocMap : ", utils.MyDocMap)

        //显示用户的输入内容
        window.myEdit.ctx.showTestText()
    }

    /**
     * 空格键处理
     * @param {*} event
     */
    emptyKeyWorkHandler(event) {
        let curP = window.myEdit.utils.GetEventTarget(event);
        let myDocItem = new MyDocItem(curP);
        let inputLength = curP.innerText.length
        // console.log("emptyKeyWorkHandler :", curP, " _'", curP.innerHTML, "'_'", curP.innerText, "'_",
        //     "\neq1", curP.innerHTML.startsWith("&nbsp;#&nbsp;"),
        //     "\neq2", curP.innerHTML.startsWith(" # "),
        //     "\neq3", curP.innerHTML.startsWith("#&nbsp;"),
        //     "\neq4", curP.innerHTML.startsWith("# "),
        //
        //     "\neqV1", curP.innerText.startsWith("&nbsp;#&nbsp;"),
        //     "\neqV2", curP.innerText.startsWith(" # "),
        //     "\neqV3", curP.innerText.startsWith("#&nbsp;"),
        //     "\neqV4", curP.innerText.startsWith("# "),
        //
        //    )
        /**
         * h1 ~ h6
         */
        if (curP.innerText.startsWith("#")) {
            let curNo = myDocItem.parseOrder();
            let mapNode = window.myEdit.ctx.MyDocMap.get(curNo);
            if (curP.innerHTML.startsWith("######")) {
                mapNode.getStyle().setNodeType("h6")
                curP.innerHTML = curP.innerHTML.replace("######", "")
                this.becomeAnotherElement(curP, "h6")
            } else if (curP.innerHTML.startsWith("#####")) {
                mapNode.getStyle().setNodeType("h5")
                curP.innerHTML = curP.innerHTML.replace("#####", "")
                this.becomeAnotherElement(curP, "h5")
            } else if (curP.innerHTML.startsWith("####")) {
                mapNode.getStyle().setNodeType("h4")
                curP.innerHTML = curP.innerHTML.replace("####", "")
                this.becomeAnotherElement(curP, "h4")
            } else if (curP.innerHTML.startsWith("###")) {
                mapNode.getStyle().setNodeType("h3")
                curP.innerHTML = curP.innerHTML.replace("###", "")
                this.becomeAnotherElement(curP, "h3")
            } else if (curP.innerHTML.startsWith("##")) {
                mapNode.getStyle().setNodeType("h2")
                curP.innerHTML = curP.innerHTML.replace("##", "")
                this.becomeAnotherElement(curP, "h2")
            } else {
                mapNode.getStyle().setNodeType("h1")
                curP.innerHTML = curP.innerHTML.replace("#", "")
                this.becomeAnotherElement(curP, "h1")
            }
        }

        /**
         * 无序列表效果
         */
        if (curP.innerText.startsWith("-")) {
            let curNo = myDocItem.parseOrder();
            let mapNode = window.myEdit.ctx.MyDocMap.get(curNo);
            mapNode.getStyle().setPreStyle("ul", true)

            //clean
            let historyContent = curP.innerHTML.replace("-", "");
            mapNode.setSource(curP.innerText)

            //根据上一层级元素动态选择 todo
            curP.setAttribute("style", "padding-left: 1rem;")
            //新增元素
            let newParagraph = document.createElement("span");
            newParagraph.setAttribute("contenteditable", "false")
            //∙ vs ∘
            newParagraph.innerHTML = "∙ &nbsp;"
            curP.innerHTML = ""
            curP.append(newParagraph);
            curP.innerHTML = curP.innerHTML + historyContent

            //收起选区到一个点,光标落在一个可编辑元素上
            window.myEdit.utils.GetSelection().collapse(curP, true)
        }

        /**
         * 有序列表效果
         */
        let preContent = curP.innerText.split("\.")[0]
        if (window.myEdit.utils.IsNum(preContent)) {
            let curNo = myDocItem.parseOrder();
            let mapNode = window.myEdit.ctx.MyDocMap.get(curNo);
            mapNode.getStyle().setPreStyle("ol", preContent)

            //clean
            let historyContent = curP.innerHTML.replace(preContent + ".", "");
            mapNode.setSource(curP.innerText)
            //todo
            curP.setAttribute("style", "padding-left: 1rem;")
            //新增元素
            let newParagraph = document.createElement("span");
            newParagraph.setAttribute("contenteditable", "false");
            newParagraph.innerHTML = preContent + ".&nbsp;"
            curP.innerHTML = ""
            curP.append(newParagraph);
            curP.innerHTML = curP.innerHTML + historyContent

            //收起选区到一个点,光标落在一个可编辑元素上
            window.myEdit.utils.GetSelection().collapse(curP, true)
        }

    }


    /**
     * 变成另一个元素
     * @param {*} elementName
     */
    becomeAnotherElement(curP, elementName) {
        let newParagraph = document.createElement(elementName)
        newParagraph.setAttribute("contenteditable", "true")
        newParagraph.setAttribute("data-id", curP.getAttribute("data-id"))
        newParagraph.setAttribute("id", curP.getAttribute("data-id"))
        newParagraph.setAttribute("data-order", curP.getAttribute("data-order"))
        newParagraph.onkeyup = window.myEdit.eventListener.KeydownListener

        //todo 支持 有数据的行 在行首输入 #
        // if()
        // switch (elementName){
        //     case "h1":
        // }
        newParagraph.innerHTML = curP.innerHTML

        window.myEdit.utils.InsertAfter(curP, newParagraph)
        curP.remove();
        curP = newParagraph;

        //matData
        let myP = new MyDocItem(curP);
        let curNo = myP.parseOrder();
        let mapNode = window.myEdit.ctx.getMapItem(curNo)
        mapNode.setSource(curP.innerText)

        //收起选区到一个点,光标落在一个可编辑元素上
        window.myEdit.utils.GetSelection().setPosition(newParagraph, 0)
    }


    /**
     * 包围样式事件处理
     * @param event
     */
    surroundContentsByStyleHandler(event) {
        let curS = window.myEdit.utils.GetSelection();
        let curP = window.myEdit.utils.GetEventTarget(event);
        let styleName = curP.getAttribute("data-value");
        if (styleName === undefined || styleName === null) {
            styleName = curP.closest("span").getAttribute("data-value");
            console.log("closest: ", curP, curP.closest("span"))
        }
        let className = this.parseStyleName2ClassName(styleName)
        //todo 只对 nodeType = p 执行
        // console.log("当前光标信息: ", curS, styleName, " className: ", className, curP)

        for (let i = 0; i < curS.rangeCount; i++) {
            let curSec = curS.getRangeAt(i);
            let curPe = curSec.commonAncestorContainer;
            //一个元素节点,例如 <p> 和 <div>。
            let curPeIsP = curPe.nodeType === 1 && curPe.nodeName === "P";
            let curPeParentIsP = curPe.parentNode.nodeType === 1 && curPe.parentNode.nodeName === "P";
            let curPeParentIsDIV = curPe.parentNode.nodeType === 1 && curPe.parentNode.nodeName === "DIV";
            let curPeParentIsSpan = curPe.parentNode.nodeType === 1 && (curPe.parentNode.nodeName === 'SPAN"' || curPe.parentNode.nodeName === 'SPAN');

            let start = curSec.startOffset;
            let end = curSec.endOffset;
            if (start > end) {
                let tmpS = start;
                start = end;
                end = tmpS;
            }
            // console.log(" 当前选区信息 : ", curSec,
            //     "\ncurPe: ", curPe,
            //     "\ncurPeP: ", curPe.parentNode, curPe.parentNode.nodeType, curPe.parentNode.nodeName,
            //
            //     "\ncurPeIsP: ", curPeIsP,
            //     "\ncurPeParentIsP : ", curPeParentIsP,
            //     "\ncurPeParentIsDIV", curPeParentIsDIV,
            //     "\ncurPeParentIsSpan", curPeParentIsSpan,
            //
            //     "\nclassName: ", className,
            //     "\ntart: ", start,
            //     "\nend: ", end)

            let curPEle = null;
            //第一次选择的时候将整行转换成<p><span></span></p>
            if (!curPeIsP && curPeParentIsP) {
                //没选择,则退出
                if (start === end) {
                    return
                } else {
                    // div
                }
                let curStartP = curSec.startContainer.parentElement;
                // console.log("debug1: ", curStartP, curStartP.nodeType, curStartP.nodeName)
                //维护最近一次编辑的内容(暂时只支持恢复最近一次编辑)
                window.myEdit.ctx.latestOpDoc = new MyRecovery(curStartP.cloneNode(true), function () {
                    console.log("恢复上一步样式1", this.innerHTML)
                    let curEl = document.getElementById(this.data.getAttribute("id"));
                    curEl.innerHTML = this.data.innerHTML;

                    //文本映射 直接覆盖 map 中的 childrenStyle
                    window.myEdit.utils.SyncMapItemChildrenStyle(this.data);
                })

                let curHtml = ""
                for (let j = 0; j < curStartP.innerText.length; j++) {
                    // console.log(curStartP.innerText.charAt(j))
                    if (j >= start && j < end) {
                        curHtml += '<span class=' + className + '>' + curStartP.innerText.charAt(j) + '</span>';
                    } else {
                        curHtml += '<span>' + curStartP.innerText.charAt(j) + '</span>';
                    }
                }

                curStartP.innerHTML = curHtml;
                curPEle = curStartP;

                //光标保持
                let s = window.getSelection();
                if (s.rangeCount > 0) s.removeAllRanges();
                let newR = document.createRange();
                //重新获取元素
                let tmpP = document.getElementById(curStartP.getAttribute("id"));
                let childrenSize = tmpP.childNodes.length;
                console.log("debug007: ", tmpP, start, end, childrenSize)
                newR.setStart(tmpP, start);
                newR.setEnd(tmpP, end);
                //区域 添加 到选区
                s.addRange(newR);
            } else {
                let tmpPNode = curSec.commonAncestorContainer;
                if (!curPeIsP && curPeParentIsSpan) {
                    tmpPNode = curSec.commonAncestorContainer.parentNode.parentNode;
                }
                // console.log("debug2: ", curSec.commonAncestorContainer, tmpPNode, tmpPNode.children, tmpPNode.childNodes)
                //维护最近一次编辑的内容(暂时只支持恢复最近一次编辑)
                window.myEdit.ctx.latestOpDoc = new MyRecovery(tmpPNode.cloneNode(true), function () {
                    console.log("恢复上一步样式1", this.data)
                    let curEl = document.getElementById(this.data.getAttribute("id"));
                    curEl.innerHTML = this.data.innerHTML;
                    //文本映射 直接覆盖 map 中的 childrenStyle
                    window.myEdit.utils.SyncMapItemChildrenStyle(this.data);
                })

                let myChildren = tmpPNode.childNodes
                // let curEleSize = tmpPNode.childNodes.length
                for (let j = 0; j < myChildren.length; j++) {
                    let curEle = myChildren[j]
                    if (curS.containsNode(curEle, true)) {
                        curEle.classList.remove(className);
                        curEle.classList.add(className);
                    }
                }

                curPEle = curSec.commonAncestorContainer;
            }


            //文本映射 直接覆盖 map 中的 childrenStyle
            window.myEdit.utils.SyncMapItemChildrenStyle(curPEle);
        }
    }
}