import titleTrans from "../func/translate/titleTrans";
import contentTitleLinksTrans from "../func/translate/contentTitleLinksTrans";
import Device from "../enum/Device";
import ActionButtonUtils from "../class/utils/ActionButtonUtils";
import CommonUtils from "../class/utils/CommonUtils";
import TRAVEL_ALARM_CSS from "../../static/css/travel_alarm.module.css";
import TRAVEL_ALARM_HTML from "../../static/html/travel_alarm.html";
import TornStyleBlock from "../class/utils/TornStyleBlock";
import QuickFlyBtnHandler from "../class/handler/QuickFlyBtnHandler";
import TRAVEL_STATE from "../enum/TravelState";
import Global from "../class/Global";
import ClassName from "../container/ClassName";
import { Injectable } from "../container/Injectable";
import LocalConfigWrapper from "../class/LocalConfigWrapper";
import MsgWrapper from "../class/utils/MsgWrapper";
import IFeature from "../man/IFeature";
import INDEX_PAGE_REG from "./url/INDEX_PAGE_REG";

/**
 * 飞行助手
 * - 飞行闹钟
 * - 一键回城
 * - 解毒提醒
 * - 落地转跳
 * - 海外警告
 */
@ClassName('TravelHelper')
@Injectable()
export default class TravelHelper implements IFeature {
    description(): string {
        return "飞行助手";
    }

    iStart(): void | Promise<void> {
        this.init()
    }

    urlExcludes(): RegExp[] {
        return [];
    }

    urlIncludes(): RegExp[] {
        return [INDEX_PAGE_REG, /travelagency\.php/];
    }

    constructor(
        private readonly global: Global,
        private readonly commonUtils: CommonUtils,
        private readonly actionButtonUtils: ActionButtonUtils,
        private readonly localConfigWrapper: LocalConfigWrapper,
        private readonly msgWrapper: MsgWrapper,
    ) {
    }

    init() {
        let { bodyAttrs, device } = this.global;
        let href = window.location.href;

        if (href.includes('index.php')) {
            switch (this.commonUtils.getTravelStage()) {
                // 飞行中
                case TRAVEL_STATE.FLYING: {
                    // 飞行闹钟
                    if (device === Device.PC && this.localConfigWrapper.config.trvAlarm) {
                        // 获取目的地
                        let dest_cn;
                        let country = document.body.getAttribute('data-country');
                        if (country === 'torn') {
                            dest_cn = '回城';
                        } else {
                            dest_cn = {
                                'uk': "英国",
                                'switzerland': "瑞士",
                                'mexico': '墨西哥',
                                'canada': '加拿大',
                                'cayman': '开曼',
                                'hawaii': '夏威夷',
                                'argentina': '阿根廷',
                                'japan': '日本',
                                'china': '中国',
                                'uae': 'UAE',
                                'south-africa': '南非',
                            }[country] || country;
                        }

                        // 剩余时间
                        const remaining_arr = document.querySelector('#countrTravel').getAttribute('data-to');

                        const wh_trv_alarm = localStorage.getItem('wh_trv_alarm')
                            ? JSON.parse(localStorage.getItem('wh_trv_alarm'))
                            : { 'enable': true, 'alert_time': 30, 'node_pos': [240, 240] };
                        const save_trv_settings = () => localStorage.setItem('wh_trv_alarm', JSON.stringify(wh_trv_alarm));

                        const wh_trv_alarm_node = document.createElement('div');
                        wh_trv_alarm_node.id = 'wh-trv-alarm';
                        wh_trv_alarm_node.style.left = `${ wh_trv_alarm.node_pos[0] }px`;
                        wh_trv_alarm_node.style.top = `${ wh_trv_alarm.node_pos[1] }px`;
                        wh_trv_alarm_node.innerHTML = TRAVEL_ALARM_HTML
                            .replace('{{}}', dest_cn === '回城' ? dest_cn : '飞往' + dest_cn)
                            .replace('{{}}', wh_trv_alarm.enable ? 'checked ' : '')
                            .replace('{{}}', wh_trv_alarm.alert_time || 30);
                        this.commonUtils.styleInject(TRAVEL_ALARM_CSS);
                        document.body.append(wh_trv_alarm_node);
                        // 报错dom
                        const error_node = wh_trv_alarm_node.querySelector('#wh-trv-error') as HTMLElement;
                        // jquery拖动
                        // @ts-ignore
                        $(wh_trv_alarm_node).draggable({
                            containment: "body",
                            distance: 5,
                            handle: "#wh-trv-alarm-title",
                            stop: () => {
                                wh_trv_alarm.node_pos = [parseInt(wh_trv_alarm_node.style.left), parseInt(wh_trv_alarm_node.style.top)];
                                save_trv_settings();
                            },
                            scroll: false,
                        });
                        // 剩余时间dom
                        const remaining_node = wh_trv_alarm_node.querySelector('#wh-trv-alarm-remaining');
                        // 设定闹钟响的按钮
                        const set_node = wh_trv_alarm_node.querySelectorAll('#wh-trv-alarm-cont button')[0] as HTMLButtonElement;
                        // 落地前响铃时长
                        const cd_time = wh_trv_alarm_node.querySelector('input[type="number"]') as HTMLInputElement;
                        set_node.onclick = () => {
                            try {
                                wh_trv_alarm.alert_time = parseInt(cd_time.value);
                            } catch {
                                wh_trv_alarm.alert_time = 30;
                            }
                            save_trv_settings();
                            set_node.value = wh_trv_alarm.alert_time;
                            this.msgWrapper.create('设置已更新');
                        };
                        // 停止响铃按钮
                        const stop_node = wh_trv_alarm_node.querySelectorAll('#wh-trv-alarm-cont button')[1] as HTMLButtonElement;
                        stop_node.onclick = () => {
                            user_stop_alert = true;
                            stop_node.innerText = '本次已关闭';
                            stop_node.disabled = true;
                        }
                        // 开启闹钟勾选
                        const enable_node = wh_trv_alarm_node.querySelector('#wh-trv-alarm-cont input[type="checkbox"]') as HTMLInputElement;
                        enable_node.onchange = ev => {
                            wh_trv_alarm.enable = (<HTMLInputElement>ev.target).checked;
                            save_trv_settings();
                            this.msgWrapper.create(wh_trv_alarm.enable ? '闹钟已开启' : '闹钟已关闭');
                        };
                        // 剩余时间 秒
                        const remaining_sec = parseInt(remaining_arr);
                        // 落地时timestamp
                        const land_timestamp = Date.now() + remaining_sec * 1000;
                        // 音频dom
                        const audio = document.createElement('audio');
                        audio.src = 'https://www.torn.com/js/chat/sounds/Warble_1.mp3';
                        audio.play()
                            .then(() => audio.pause())
                            .catch(() => {
                                error_node.style.display = 'table';
                                const func = () => {
                                    error_node.remove();
                                    document.body.removeEventListener('click', func);
                                };
                                document.body.addEventListener('click', func);
                            });
                        // 是否正在响铃
                        let audio_play_flag = false;
                        // 用户是否停止当前响铃
                        let user_stop_alert = false;
                        // 响铃循环id
                        let audio_play_id = null;
                        // 响铃的方法
                        let audio_play_handle = () => {
                            if (user_stop_alert) {
                                window.clearInterval(audio_play_id);
                                audio_play_id = null;
                                return;
                            }
                            if (!audio_play_flag || !wh_trv_alarm.enable) return;
                            audio.play().then();
                        };
                        // 飞机小动画字符
                        const flying_arr = [
                            '✈ ',
                            '&nbsp;&nbsp;✈ ',
                            '&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
                            '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
                            '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
                            '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
                            '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
                            '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
                            '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
                            '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✈ ',
                        ];
                        // 飞行的状态dom
                        const flying_status = wh_trv_alarm_node.querySelector('#wh-trv-status');
                        // 飞机的小动画dom
                        const flying_ani = flying_status.nextElementSibling;
                        // 飞机的计数
                        let flying_index = 0;
                        const id = window.setInterval(() => {
                            const remaining_time = (land_timestamp - Date.now()) / 1000 | 0;
                            remaining_node.innerText = `${ remaining_time / 3600 | 0 }时${ remaining_time % 3600 / 60 | 0 }分${ remaining_time % 60 }秒`;

                            if (remaining_time < wh_trv_alarm.alert_time) {
                                // flying_status.innerHTML = `即将落地...`;
                                if (wh_trv_alarm.enable) {
                                    // 播放提示音
                                    audio_play_flag = true;
                                    if (audio_play_id === null && !user_stop_alert) audio_play_id = window.setInterval(audio_play_handle, 750);
                                    stop_node.parentElement.classList.remove('wh-trv-alarm-stop-hide');
                                }
                            } else {
                                // flying_status.innerHTML = `飞行中...`;
                                if (wh_trv_alarm.enable) {
                                    window.clearInterval(audio_play_id);
                                    audio_play_id = null;
                                    stop_node.parentElement.classList.add('wh-trv-alarm-stop-hide');
                                }
                            }
                            flying_ani.innerHTML = `${ flying_arr[flying_index] }`;
                            flying_index = (flying_index + 1) % flying_arr.length;
                        }, 1000);
                    }

                    // 落地转跳 落地前事件
                    if (this.localConfigWrapper.config.landedRedirect && document.querySelector('#tcLogo[title]') === null) {
                        window.addEventListener('beforeunload', () => {
                            let obj = { url: this.localConfigWrapper.config.landedRedirect, timestamp: Date.now() };
                            sessionStorage['wh-landed-redirect'] = JSON.stringify(obj);
                        });
                    }
                    break;
                }
                // 海外落地
                case TRAVEL_STATE.ABROAD: {
                    // 一键回城
                    this.actionButtonUtils.add('直接回城', () => this.doTravelBack());
                    // 海外警告
                    if (this.localConfigWrapper.config.abroadWarning) {
                        let c = 1;
                        setInterval(() => this.msgWrapper.create(`警告：您已海外落地${ c++ * 30 }秒`, {
                            timeout: 30,
                            sysNotify: true
                        }), 30000);
                    }
                    // 解毒提醒
                    if (bodyAttrs['data-country'] === 'switzerland') {
                        let block = new TornStyleBlock('解毒提醒');
                        block.setContent('<p><a href="/index.php?page=rehab">❤️ 点击前往解毒</a></p>');
                        document.querySelector('h4#skip-to-content').before(block.getBase());
                    }
                    break;
                }
                // 主页界面
                case TRAVEL_STATE.IN_TORN: {
                    // 落地转跳
                    if (sessionStorage['wh-landed-redirect']) {
                        let { url, timestamp } = JSON.parse(sessionStorage['wh-landed-redirect']);
                        if (Date.now() - timestamp < 30000) {
                            sessionStorage.removeItem('wh-landed-redirect');
                            location.href = url;
                        }
                    }
                    break;
                }
            }
        }
        // 起飞页面
        else if (href.contains(/travelagency\.php/)) {
            // 起飞提醒 TODO 去除jquery mutation
            if (this.localConfigWrapper.config.energyAlert) {
                const contentWrapper = document.querySelector('.content-wrapper');
                const OB = new MutationObserver(() => {
                    OB.disconnect();
                    titleTrans();
                    contentTitleLinksTrans();
                    trans();
                    OB.observe(contentWrapper, {
                        characterData: true,
                        attributes: true,
                        subtree: true,
                        childList: true
                    });
                });
                const trans = () => {
                    // 当前能量e
                    // @ts-ignore
                    const energyBarStr = $('#barEnergy p[class^="bar-value__"]').text().trim();
                    const [curE, maxE] = energyBarStr.split('/').length === 2
                        ? [parseInt(energyBarStr.split('/')[0]), parseInt(energyBarStr.split('/')[1])]
                        : [NaN, NaN];
                    const incTime = maxE === 150 ? 10 : 15;
                    const fullEnergyTime = !(isNaN(curE) || isNaN(maxE)) ? (maxE - 5 - curE) / 5 * incTime
                        + (incTime - new Date().getMinutes() % incTime) : NaN;
                    // 起飞前提示
                    // @ts-ignore
                    $('.travel-confirm .travel-question .q-wrap span:nth-of-type(2)').each((i, e) => {
                        if (isNaN(fullEnergyTime)) return;
                        const spl = e.innerText.trim().split(' ');
                        const [hours, minutes] = spl.length === 5
                            ? [parseInt(spl[0]), parseInt(spl[3])]
                            : [0, parseInt(spl[0])];
                        if (fullEnergyTime < (hours * 60 + minutes) * 2) {
                            if (!$(e).parent().hasClass('wh-translated')) {
                                $(e).parent()
                                    .prepend(`<div style="color: red">警告：该次飞行往返时间大于体力回复时间，将会爆体！</div>`)
                                    .addClass('wh-translated');
                            }
                        }
                    });
                };
                trans();
                OB.observe(contentWrapper, {
                    characterData: true,
                    attributes: true,
                    subtree: true,
                    childList: true
                });
            }
            // 一键起飞
            if (window.sessionStorage['wh-quick-fly']) {
                QuickFlyBtnHandler.doQuickFly();
            }
        }
    }

    async doTravelBack(): Promise<void> {
        if (typeof window['getAction'] !== 'function') return;
        let backHomeAction = function (): Promise<string> {
            return new Promise(resolve => {
                window.getAction({
                    type: "post",
                    action: 'travelagency.php',
                    data: {
                        step: 'backHomeAction'
                    },
                    success: function (msg) {
                        resolve(msg);
                    }
                });
            });
        };
        let res = await backHomeAction();
        this.msgWrapper.create(res);
        if (!res.includes('error')) {
            this.msgWrapper.create('成功，即将刷新');
            window.setTimeout(() => location.reload(), 3000);
        } else {
            this.msgWrapper.create('出错了');
        }
    }
}
