import adHelper from "../func/module/adHelper";
import safeKeeper from "../func/module/safeKeeper";
import initMiniProf from "../func/utils/initMiniProf";
import CommonUtils from "./utils/CommonUtils";
import * as EVENTS from "../../static/json/event.json";
import * as FEST from "../../static/json/fest.json";
import Popup from "./utils/Popup";
import TravelItem from "../feature/TravelItem";
import ZHONG_MENU_HTML from "../../static/html/zhong/zhong_menu.html";
import ZHONG_UPDATE_HTML from "../../static/html/zhong/zhong_update.html";
import ZHONG_LOOT_HTML from "../../static/html/zhong/zhong_loot.html";
import Test from "../test/Test";
import Timer from "./utils/Timer";
import QuickFlyBtnHandler from "./handler/QuickFlyBtnHandler";
import NNB from "./handler/NNB";
import QuickLinksHandler from "./handler/QuickLinksHandler";
import ItemPriceWatcherHandler from "./handler/ItemPriceWatcherHandler";
// import ChangeLogHandler from "./handler/ChangeLogHandler";
import ItemPriceHandler from "./handler/ItemPriceHandler";
import SettingsHandler from "./handler/SettingsHandler";
import { MENU_ITEM_TYPE } from "../interface/MenuItem";
import { Injectable } from "../container/Injectable";
import ClassName from "../container/ClassName";
import LocalConfigWrapper from "./LocalConfigWrapper";
import Logger from "./Logger";
import { Container } from "../container/Container";
import TornPDAUtils from "./utils/TornPDAUtils";
import InfoUtils from "./utils/InfoUtils";
import globVars from "../globVars";
import MsgWrapper from "./utils/MsgWrapper";

@Injectable()
@ClassName('ZhongIcon')
export default class ZhongIcon {
    public static ZhongNode: MyHTMLElement = null;
    private menuItemList: MenuItemConfig[] = null;
    private cashView: HTMLElement = null;

    public constructor(
        private readonly commonUtils: CommonUtils,
        private readonly localConfigWrapper: LocalConfigWrapper,
        private readonly nnb: NNB,
        private readonly itemPriceWatcherHandler: ItemPriceWatcherHandler,
        private readonly logger: Logger,
        private readonly tornPDAUtils: TornPDAUtils,
        private readonly infoUtils: InfoUtils,
        private readonly msgWrapper: MsgWrapper,
    ) {
    }

    public init() {
        this.constructMenuList()
            .insert2Dom()
            .dragHandler();
        this.logger.info('设置图标结束');
    }

    public updateCashView(content: string): void {
        if (!this.cashView || !ZhongIcon.ZhongNode.contains(this.cashView)) {
            this.cashView = document.createElement('div');
            this.cashView.id = 'wh-cash-monitor';
            ZhongIcon.ZhongNode.append(this.cashView);
        }
        this.cashView.innerText = content;
    }

    private static setPosition(x: number, y: number) {
        if (!(x && y)) return;
        if (x > 0 && x < document.documentElement.offsetWidth - 100) {
            ZhongIcon.ZhongNode.style.left = x + "px";
        }
        if (y > 0 && y < document.documentElement.offsetHeight - 60) {
            ZhongIcon.ZhongNode.style.top = y + "px";
        }
    }

    /**
     * 添加左侧图标
     */
    private insert2Dom(): ZhongIcon {
        let zhongNode: MyHTMLElement = document.querySelector('div#wh-trans-icon');
        let version = globVars.version;
        if ((self !== top) || !!zhongNode) return null;
        zhongNode = document.createElement('div');
        ZhongIcon.ZhongNode = zhongNode;
        zhongNode.id = 'wh-trans-icon';
        zhongNode.classList.add('cont-gray');
        zhongNode.innerHTML = ZHONG_MENU_HTML.replace('{{}}', version.slice(-1) === '$' ? 'DEV' : version);
        // 助手菜单
        const menu_cont = zhongNode.querySelector('#wh-gSettings');
        // 遍历菜单node设置、生成node、插入dom
        this.menuItemList.forEach(setting => this.commonUtils.elemGenerator(setting, menu_cont));
        this.logger.info('生成元素插入完成');
        // 计时node
        zhongNode.initTimer = zhongNode.querySelector('#wh-inittimer');
        // 芜湖助手图标点击事件
        (<MyHTMLElement>zhongNode.querySelector('#wh-trans-icon-btn')).onclick = () => {
            zhongNode.classList.toggle('wh-icon-expanded');
            const click_func = e => {
                this.logger.info(e.target);
                if (e.target === zhongNode.querySelector('#wh-trans-icon-btn')) return;
                if (!zhongNode.contains(e.target)) {
                    this.logger.info('移除事件监听器');
                    document.body.removeEventListener('click', click_func);
                    zhongNode.classList.remove('wh-icon-expanded');
                }
            };
            if (zhongNode.classList.contains('wh-icon-expanded')) {
                this.logger.info('芜湖助手图标点击->添加监听');
                document.body.addEventListener('click', click_func);
            } else {
                this.logger.info('芜湖助手图标->移除监听');
                document.body.removeEventListener('click', click_func);
            }
        };
        // 更新按钮点击事件
        (<MyHTMLElement>zhongNode.querySelector('#wh-update-btn')).onclick = e => {
            (<HTMLButtonElement>e.target).blur();
            // 直接复制的按钮
            new Popup(ZHONG_UPDATE_HTML, '如何更新')
                .element
                .querySelector('button').onclick = async (e) => {
                let target = e.target as HTMLButtonElement;
                target.innerHTML = '加载中';
                const js_text = await CommonUtils.COFetch(`https://jjins.github.io/fyfuzhi/release.min.user.js?${ performance.now() }`);
                target.innerHTML = '点击复制到剪切板';
                target.onclick = () => {
                    const textarea_node = document.createElement('textarea');
                    textarea_node.innerHTML = js_text;
                    target.parentElement.append(textarea_node);
                    textarea_node.focus();
                    textarea_node.select();
                    document.execCommand('Copy');
                    textarea_node.remove();
                    target.innerHTML = '已复制';
                    target.onclick = null;
                    this.msgWrapper.create('脚本已复制，请前往粘贴');
                };
            };
        };
        // 节日
        zhongNode.querySelectorAll('#wh-trans-fest-date button').forEach((el, i) => i === 0
            ? el.addEventListener('click', () => {
                let html = '<table>';
                // TODO 动态节日数据
                Object.keys(FEST.val).sort().forEach(date =>
                    html += `<tr><td>${ 1 + ((<any>date.slice(0, 2)) | 0) }月${ date.slice(2) }日</td><td>${ FEST.val[date].name }</td><td>${ FEST.val[date].eff }</td></tr>`
                );
                new Popup(html += '</table>', '节日');
            })
            : el.addEventListener('click', null));
        // 活动
        zhongNode.querySelectorAll('#wh-trans-event-cont button').forEach((el, i) => i === 0
            ? el.addEventListener('click', () => {
                let html = '<table>';
                // TODO 动态节日数据
                EVENTS.default.forEach(el =>
                    html += `<tr><td><b>${ el.name }</b></td><td>${ el.start[0] + 1 }月${ el.start[1] }日${ el.start[2] }:00~${ el.end[0] + 1 }月${ el.end[1] }日${ el.end[2] }:00</td></tr><tr><td colspan="2">${ el.eff }</td></tr>`);
                new Popup(html += '</table><p>更多信息请关注群聊和公众号</p>', '活动');
            })
            : el.addEventListener('click', null));
        // 调整图标至有记录的位置
        if (this.localConfigWrapper.config.SaveIconPosition) {
            let iconPosition = this.localConfigWrapper.config.IconPosition;
            let documentSize = { x: document.documentElement.offsetWidth, y: document.documentElement.offsetHeight };
            ZhongIcon.setPosition(
                iconPosition.x > documentSize.x ? documentSize.x * 0.9 | 0 : iconPosition.x,
                iconPosition.y > documentSize.y ? documentSize.y * 0.9 | 0 : iconPosition.y
            );
        }
        document.body.append(zhongNode);
        // 引入torn自带浮动提示
        this.logger.info('引入torn浮动提示');
        (window.initializeTooltip) && (window.initializeTooltip('.wh-container', 'white-tooltip'));
        // 加载torn mini profile
        this.logger.info('加载torn mini profile');
        let miniProfileInterval = {
            id: window.setInterval(() => {
                miniProfileInterval.counter++;
                if (window.$ || (window.unsafeWindow && window.unsafeWindow.$)) {
                    initMiniProf('#wh-trans-icon');
                    window.clearInterval(miniProfileInterval.id);
                }
                if (miniProfileInterval.counter > 30) window.clearInterval(miniProfileInterval.id);
            }, 1000),
            counter: 0
        };
        this.logger.info('图标加入文档树');
        return this;
    }

    private dragHandler(): ZhongIcon {
        let isMouseDown = false;
        let isMouseMoved = false;
        let offsetXY = { x: 0, y: 0 };
        ZhongIcon.ZhongNode.addEventListener('mousedown', (e) => {
            if (e.button === 0) {
                e.preventDefault();
                isMouseDown = true;
                let nodeXY = ZhongIcon.getPosition();
                offsetXY.x = e.x - nodeXY.x;
                offsetXY.y = e.y - nodeXY.y;
            }
        });
        document.addEventListener('mouseup', () => {
            isMouseDown = false;
            if (isMouseMoved) {
                isMouseMoved = false;
                if (this.localConfigWrapper.config.SaveIconPosition) {
                    this.localConfigWrapper.config.IconPosition = ZhongIcon.getPosition();
                }
            }
        });
        document.addEventListener('mousemove', (e) => {
            if (isMouseDown) {
                ZhongIcon.setPosition(e.x - offsetXY.x, e.y - offsetXY.y);
                isMouseMoved = true;
            }
        });
        return this;
    }

    private static getPosition(): { x: number, y: number } {
        return {
            x: ZhongIcon.ZhongNode.style.left ? parseInt(ZhongIcon.ZhongNode.style.left.slice(0, -2)) : ZhongIcon.ZhongNode.offsetLeft,
            y: ZhongIcon.ZhongNode.style.top ? parseInt(ZhongIcon.ZhongNode.style.top.slice(0, -2)) : ZhongIcon.ZhongNode.offsetTop
        }
    }

    // 菜单
    private constructMenuList(): ZhongIcon {
        this.logger.info('构造菜单列表开始');
        let timer = new Timer();
        const date = new Date();
        let userInfo = this.infoUtils.getPlayerInfo();

        let list: MenuItemConfig[] = [];

        // 欢迎 显示玩家id
        if (userInfo.userID !== 0) {
            list.push({
                domType: 'plain',
                domId: 'wh-trans-welcome',
                domHTML:
                    `<a href="/profiles.php?XID=${ userInfo.userID }" target="_blank">${ userInfo.playername }</a>[${ userInfo.userID }]`,
            });
        }
        // 节日
        let fest_date_html = '<button>节日</button>: ';
        {
            // 节日字典
            const dict = FEST.val;
            // list.fest_date_dict = dict;
            // list.fest_date_list = Object.keys(dict);
            const formatMMDD = (m, d) => {
                const MM = m < 10 ? `0${ m }` : m.toString();
                const DD = d < 10 ? `0${ d }` : d.toString();
                return MM + DD;
            }
            const fest_date_key = formatMMDD(date.getUTCMonth(), date.getUTCDate());
            if (dict[fest_date_key]) fest_date_html += `今天 - ${ dict[fest_date_key]['name'] }(<button title="${ dict[fest_date_key]['eff'] }">效果</button>)`;
            else {
                // 月日列表
                let list = Object.keys(dict);
                list.push(fest_date_key);
                // 下个节日的位置
                const index: number = list.sort().indexOf(fest_date_key) + 1;
                // 下个节日obj
                const next_fest_date = dict[list[index] || list[0]];
                // 下个节日的时间
                let next = new Date(
                    index !== list.length ? date.getUTCFullYear() : date.getUTCFullYear() + 1,
                    (list[index !== list.length ? index : 0] as any).slice(0, 2) | 0,
                    (list[index !== list.length ? index : 0] as any).slice(2) | 0,
                    8
                ).getTime();
                // 剩余天数
                const left = (next - date.getTime()) / 86400000 | 0;
                fest_date_html += `${ left }天后 - ${ next_fest_date.name }(<button title="${ next_fest_date.eff }">效果</button>)`;
            }
        }
        list.push({
            domType: 'plain',
            domId: 'wh-trans-fest-date',
            domHTML: fest_date_html,
        });
        // 活动
        let eventObj: EventWrapper = {
            onEv: false,
            daysLeft: Infinity,
            events: EVENTS.default,
        };
        list.events = EVENTS.default;
        eventObj.events.forEach((obj, index) => {
            if (eventObj.onEv) return;
            // 当前年份
            const nowYear = date.getFullYear();
            // 当前遍历的活动开始时间
            const start = new Date(nowYear, obj.start[0], obj.start[1], obj.start[2]);
            // 当前遍历的活动结束时间
            const end = new Date(nowYear, obj.end[0], obj.end[1], obj.end[2]);
            // 当前处于活动中
            if (start < date && date < end) {
                eventObj.onEv = true;
                eventObj.daysLeft = (end.getTime() - date.getTime()) / 86400000 | 0;
                eventObj.current = obj;
            }
            // 当前没有活动
            else {
                // 当前遍历的活动如果已经经过了，那么下次活动就是遍历的下一个活动对象，否则为当前活动。
                // 如果本年度活动都经过了，那么下次活动是列表的第一个活动对象
                const next = end < date ? eventObj.events[index + 1] || eventObj.events[0] : obj;
                // 经过了最后一个活动所以下次活动开始时间是第二年
                const start = new Date(next !== obj && index === eventObj.events.length - 1 ? nowYear + 1 : nowYear, next.start[0], next.start[1], next.start[2]);
                const daysLeft = (start.getTime() - date.getTime()) / 86400000 | 0;
                if (0 <= daysLeft && daysLeft < eventObj.daysLeft) {
                    eventObj.daysLeft = daysLeft;
                    eventObj.next = next;
                }
            }
        });
        eventObj.html = '<button>活动</button>: ';
        eventObj.onEv
            ? eventObj.html += `${ eventObj.current.name }(<button title="${ eventObj.current.eff }">详情</button>) - 剩余${ eventObj.daysLeft }天`
            : eventObj.html += `${ eventObj.daysLeft }天后 - ${ eventObj.next.name }(<button title="${ eventObj.next.eff }">详情</button>)`;
        list.push({
            domType: 'plain',
            domId: 'wh-trans-event-cont',
            domHTML: eventObj.html,
        });
        // 一键起飞
        list.push({
            domType: 'button',
            domId: 'wh-quick-fly-btn',
            domText: '✈️ 一键起飞',
            clickFunc: () => Container.factory(QuickFlyBtnHandler).handle(),
        });
        // 飞花库存
        list.push({
            domType: 'button',
            domId: 'wh-foreign-stock-btn',
            domText: '🌸 飞花库存',
            clickFunc: () => Container.factory(TravelItem).clickHandler().then(),
        });
        // NPC LOOT
        list.push({
            domType: 'button',
            domId: 'wh-npc-loot-btn',
            domText: '🔫 LOOT',
            clickFunc: () => {
                const insert = ZHONG_LOOT_HTML.replace('{{}}', performance.now().toString());
                new Popup(insert, 'NPC LOOT');
            },
            tip: '显示5个可击杀NPC的开打时间',
        });
        // 查看NNB
        list.push({
            domType: 'button',
            domId: 'wh-nnb-info',
            domText: '👮‍ 查看NNB',
            clickFunc: () => this.nnb.handle(),
        });
        // 常用链接
        list.push({
            domType: 'button',
            domId: 'wh-link-collection',
            domText: '🔗 常用链接',
            clickFunc: () => Container.factory(QuickLinksHandler).handle()
        });
        // 飞贼
        // list.push({
        //     domType: 'button',
        //     domId: 'wh-gs-btn',
        //     domText: '🐏 飞贼小助手',
        //     clickFunc: () => loadGS(CommonUtils.getScriptEngine()),
        //     tip: '加载从PC端移植的伞佬的油猴版飞贼小助手',
        // });

        // 物品价格监视
        list.push({
            domType: 'button',
            domId: 'wh-price-watcher-btn',
            domText: '💊 价格监视',
            clickFunc: () => this.itemPriceWatcherHandler.handle()
        });
        // 全屏
        if (!this.tornPDAUtils.isPDA()) list.push({
            domType: 'button', domId: '', domText: '🖥️ 进入全屏', clickFunc() {
                document.documentElement.requestFullscreen().then();
            }
        });
        // 传单助手
        list.push({
            domType: 'button',
            domId: '',
            domText: '📜️ 传单助手',
            clickFunc: adHelper
        });
        // 守望者
        list.push({
            domType: 'button',
            domId: '',
            domText: '🛡️ 守望者',
            clickFunc: function () {
                safeKeeper();
            },
        });
        // 寻找木桩
        list.push({
            domType: 'button',
            domId: '',
            domText: '🌲 寻找木桩',
            clickFunc() {
                window.location.replace('https://www.torn.com/item.php?temp=4#xunzhaomuzhuang')
            }
        });
        // 物品查价
        list.push(ItemPriceHandler);
        // 更新历史
        // list.push(ChangeLogHandler);
        // 助手设置
        list.push(SettingsHandler);
        // 测试
        if (this.logger.debug()) list.push(Test);

        this.menuItemList = list;
        this.logger.info('构造展开菜单列表结束' + timer.getTimeMs());
        return this;
    }
}

export interface MenuItemConfig {
    domType: 'button' | 'plain' | 'checkbox' | 'select' | MENU_ITEM_TYPE;
    tagName?: string;
    domId?: string;
    domText?: string;
    clickFunc?: (ev?) => void;
    domHTML?: string;
    tip?: string;
    dictName?: string;
    changeEv?: (ev) => void;
    domSelectOpt?: { domVal: string, domText: string }[];
    /**
     * 隐藏菜单已弃用
     * @deprecated
     */
    isHide?: boolean;
    isTornBtn?: boolean;
}

interface EventWrapper {
    onEv: boolean;
    daysLeft: number;
    events: Event[];
    current?: Event;
    next?: Event;
    html?: string;
}

interface Event {
    start: number[];
    end: number[];
    name: string;
    eff: string;
}
