import {StreamOpt, StreamSpeed} from "../../model/playerModel";
import httpClient from "../../core/httpClient";
import TimeLine, {format} from "./timeline/timeline.es"
import {getDateStrBySize} from "../utils";
import * as AirDatepicker from "air-datepicker/air-datepicker.js";
import localeZh from 'air-datepicker/locale/zh';
import {EventEmitter} from 'events'
import {streamSpeedIconMap} from "../icons";
const prefixName = 'JPlayer'

interface timeOP {
    beginTime: string
    endTime: string
    size: string
}

class vodPlayer {
    private streamOpt: StreamOpt;
    private timeline: TimeLine
    private allListTime: timeOP[] // 时间轴（前后时间）
    private runListTime: timeOP[] // 时间轴会运动的时间
    private shiftingTime: number = 0 // 每一段中间的空挡时间
    private el: any
    private picker: any
    private param = {
        time: 0,
        cont: 24
    };
    private requestInfo: { url: string, headers: any }
    private size = 'lg'
    public _streamSpeed: StreamSpeed = 0; // 录像模式下流播放速度
    private loading = false;
    private process: HTMLElement;
    private timeHandle: HTMLElement;
    private recordTip: number | null = null;
    private isTip = true;
    emitter: any

    constructor(stream: StreamOpt,size:string, el: Element, requestInfo: { url: string, headers: any }) {
        this.streamOpt = stream
        this.size = size
        this.el = el
        this.requestInfo = requestInfo
        this.emitter = new EventEmitter()
    }

    on(event: any, listener: any) {
        this.emitter.addListener(event, listener);
    }

    off(event: any, listener: any) {
        this.emitter.removeListener(event, listener);
    }

    // 初始化
    init() {
        const videoBox = this.el.querySelector("." + prefixName + "-video-box");
        const process = document.createElement('div')
        process.className = `${prefixName}-toolbar ${prefixName}-process`
        // 时间线
        const timeLine = document.createElement("canvas")
        timeLine.id = `${prefixName}-time-line`
        process.appendChild(timeLine)
        // 控制按钮
        const timeHandle = document.createElement("div")
        timeHandle.className = `${prefixName}-time-handle`
        timeHandle.innerHTML=`<div class="time--card"><div class="time--left">-</div><div class="time--signal">24h</div><div class="time--right">+</div></div>`
        process.appendChild(timeHandle)
        //
        videoBox.appendChild(process)
        this.process = process
        this.timeHandle = timeHandle
        process.addEventListener('click', (e) => {
            e.stopPropagation()
        })
        const _height = 30
        this.timeline = new TimeLine(timeLine, {
            fill: true, // 适应父容器
            zoom: 0,
            height: _height,
            textColor: '#fff',
            scaleColor: '#000',
            pointerColor: '#fff',
            bgColor: 'rgba(255,255,255,0.3)',
            areaBgColor: '#',
            pointerWidth: 2,
            pointerDisplayWidth: 0,
            pointerDisplayHeight: 100,
            bgTextColor: 'transparent',
            scaleHeight: {long: _height / 5.2, short: _height / 9.6},
            timeSpacingList: [720000, 360000, 180000, 60000],
            thresholdsConfig: {
                720000: {
                    scaleTimeFormat: "HH:mm",
                    bgTimeFormat: "YYYY/MM/DD",
                    pointerTimeFormat: "HH:mm",
                    space: 10,
                },
                360000: {
                    scaleTimeFormat: "HH:mm",
                    bgTimeFormat: "YYYY/MM/DD",
                    pointerTimeFormat: "HH:mm",
                    space: 10,
                },
                180000: {
                    scaleTimeFormat: "HH:mm",
                    bgTimeFormat: "YYYY/MM/DD",
                    pointerTimeFormat: "HH:mm",
                    space: 10,
                },
                60000: {
                    scaleTimeFormat: "HH:mm",
                    bgTimeFormat: "YYYY/MM/DD",
                    pointerTimeFormat: "HH:mm",
                    space: 10,
                }
            }
        })
        this.setTimelineEvent()
        this.setLineData(this.param.time)
        this.initPicker()
    }

    // 设置时间事件
    setTimelineEvent(create = true){
        const timeSignal = this.timeHandle.querySelector('.time--signal')
        const timeLeft = this.timeHandle.querySelector('.time--left')
        const timeRight = this.timeHandle.querySelector('.time--right')
        const setTimeSignal=(spacing:number)=>{
            let text = '24h'
            switch (spacing){
                case 720000: text = '24h';break
                case 360000: text = '12h';break
                case 180000: text = '6h';break
                case 60000: text = '2h';break
            }
            timeSignal.innerHTML = text
        }
        if(create){
            this.timeline.on('dragged', async (timestamp: any) => {
                const cmdBody = {
                    cmd: "seek",
                    startTime: format(timestamp, 'YYYY-MM-DDTHH:mm:ss.SSSZ'),
                    endTime: format(timestamp + (12 * 3600000), 'YYYY-MM-DDTHH:mm:ss.SSSZ'),
                }
                this.emitter.emit('vod-send', cmdBody)
                this.isTip = false
                await this.queryRecord({dateTime: format(timestamp, 'YYYY-MM-DD HH:mm')} as any)
                this.setLineData(this.param.time)
            })
            this.timeline.on('zoom',(spacing:number)=>{
                setTimeSignal(spacing)
            })
            timeLeft.addEventListener('click',(e)=>{
                setTimeSignal(this.timeline.setZoom(true))
            })
            timeRight.addEventListener('click',(e)=>{
                setTimeSignal(this.timeline.setZoom(false))
            })
            return
        }

        timeLeft.removeEventListener('click',(e)=>{
            setTimeSignal(this.timeline.setZoom(true))
        },false)

        timeRight.removeEventListener('click',(e)=>{
            setTimeSignal(this.timeline.setZoom(false))
        })
    }

    // 设置数据
    setLineData(currentTime: number) {
        const list = this.allListTime.map(v => {
            return {
                startTime: Date.parse(v.beginTime),
                endTime: Date.parse(v.endTime),
                bgColor: 'rgba(0,115,229,0.7)'
            }
        })
        this.timeline.draw({
            currentTime,
            areas: list
        } as any)
    }

    // 阻止浏览器冒泡
    setStopPropagation(e){
        e.stopPropagation();
    }

    // 初始化时间选择器
    initPicker() {
        const wrapperel = this.el.querySelector("." + prefixName + "-wrapper");
        const pickerEl = this.el.querySelector(".picker");
        if (!pickerEl) {
            return;
        }
        const el = pickerEl.querySelector(".time-clock-item.range");
        const input = document.createElement('input')
        el.appendChild(input)
        if (this.picker) {
            this.picker.destroy();
            this.picker = null;
        }
        const _param = {
            ...this.param,
            isConf: false
        }
        const confButton = {
            content: "关闭",
            className: "close-button-classname",
            onClick: (dp: any) => {
                dp.hide();
            },
        };
        const closeButton = {
            content: "确定",
            className: "conf-button-classname",
            onClick: (dp: any) => {
                _param.isConf = true
                this.isTip = true
                dp.update(dp.selectedDates);
                dp.hide();
                this.emitter.emit('vod-refresh', {
                    dataTime:format(dp.selectedDates, 'YYYY-MM-DD HH:mm'),
                    vod: this.streamOpt.vod
                })
            }
        }
        const opt = {
            // visible: true,
            // inline: true,
            // navTitles: {days: "yyyy - MM"},
            // clearButton: true,
            // minDate: new Date().getTime() - 1000 * 3600 * 24 * 30,
            autoClose: false,
            timepicker: true,
            toggleSelected: true,
            locale: localeZh,
            maxDate: new Date(),
            position: "top center",
            buttons: [confButton, closeButton],
            container: wrapperel,
            dateFormat: (e: any) => {
                return getDateStrBySize(e, this.size);
            },
            onSelect: (dp: any) => {
                if (dp) {
                    dp.datepicker.setViewDate(this.param.time);
                }
            },
            onShow: (dp: any) => {
                // if (dp) {
                //     _param.isConf = false
                //     _param.cont = parseInt(span.innerHTML)
                // }
            },
            onHide: (dp: any) => {
                // if (dp && !_param.isConf) {
                //     this.picker.selectDate(this.param.time, {updateTime: true});
                //     span.innerHTML = this.param.cont + ''
                // }
            }
        };
        this.picker = new (AirDatepicker as any)(el, opt);
        this.picker.clear();
        this.picker.selectDate(this.param.time, {updateTime: true});
        this.picker.setViewDate(this.param.time);
        this.picker.$datepicker.addEventListener("click", this.setStopPropagation,false)
    }

    // 增加倍速
    addStreamSpeed() {
        const {_streamSpeed} = this;
        if (_streamSpeed >= 3) return;
        this.setStreamSpeed(_streamSpeed + 1 as StreamSpeed);
    }

    // 减少倍速
    reduceStreamSpeed() {
        const {_streamSpeed} = this;
        if (_streamSpeed <= -3) return;
        this.setStreamSpeed(_streamSpeed - 1 as StreamSpeed)
    }

    // 修改倍数
    setStreamSpeed(v: StreamSpeed) {
        let rate = 1
        switch (v) {
            case 0:
                rate = 1;
                break
            case 1:
                rate = 2;
                break
            case 2:
                rate = 4;
                break
            case 3:
                rate = 8;
                break
            case -1:
                rate = -2;
                break
            case -2:
                rate = -4;
                break
            case -3:
                rate = -8;
                break
        }
        const cmdBody = {
            v,
            rate,
            cmd: "speed",
        }
        this.emitter.emit('vod-send', cmdBody)
    }

    setSpeed(val: any) {
        if (val.cmd === 'speed') {
            this._streamSpeed = val.v
            this.upDateSpeedView(this._streamSpeed)
        }
    }

    // 更新倍速视图
    upDateSpeedView(streamSpeed: StreamSpeed) {
        const txt = this.el.querySelector(".stream-speed-text");
        const right = this.el.querySelector(".stream-speed-add");
        const left = this.el.querySelector(".stream-speed-reduce");
        if (!txt) {
            return;
        }
        txt.innerHTML = streamSpeedIconMap(streamSpeed)
        right.classList.remove("disabled");
        left.classList.remove("disabled");
        if (streamSpeed === 3) {
            right.classList.add("disabled");
        } else if (streamSpeed === -3) {
            left.classList.add("disabled");
        }
    }

    // 设置时间
    setDateHour(date: string, hour: number, isType = true) {
        const curTime = new Date(date);
        const hourStr = isType ? curTime.getHours() + hour : curTime.getHours() - hour;
        return curTime.setHours(hourStr);
    }

    // 查询录像时间段
    async queryRecord(stream: StreamOpt,isEmit = true) {  // 查询录像时间段
        this.loading = true
        let verify = true
        this.streamOpt = {...this.streamOpt, ...stream}
        for (let i=0; i<2; i++){
            const {url, headers} = this.requestInfo
            const { headerToolBar, footerToolBar, title, vod, protocol, ...param} = this.streamOpt;
            const now = new Date();
            const queryTime = param.dateTime || param.beginTime
            const dateTime = queryTime || format(new Date(now.getTime() - 30 * 60 * 1000), 'YYYY-MM-DD HH:mm')
            const hour = this.param.cont / 2
            const objTime1 = {
                beginTime: format(dateTime, 'YYYY-MM-DDTHH:mm:ss.SSSZ'),
                endTime: format(this.setDateHour(dateTime, hour, true), 'YYYY-MM-DDTHH:mm:ss.SSSZ'),
            }
            const objTime2 = {
                beginTime: format(this.setDateHour(dateTime, hour, false), 'YYYY-MM-DDTHH:mm:ss.SSSZ'),
                endTime: format(dateTime, 'YYYY-MM-DDTHH:mm:ss.SSSZ'),
            }
            const sameObj = {
                protocol,
                aisleId: param.aisleId,
                recordLocation: vod + '',
                needReturnClipInfo: true,
            }
            const res = await Promise.all([
                httpClient.post(url, {
                    ...sameObj,
                    ...objTime1,
                }, headers),
                httpClient.post(url, {
                    ...sameObj,
                    ...objTime2,
                }, headers)
            ]).catch((err) => {
                this.loading = false
                return Promise.reject(err)
            })
            res.forEach((v, index) => {
                if (v.code === 0 && v.data?.list?.length > 0) {
                    verify = true
                    if (index === 0) {
                        this.streamOpt.vod = vod
                        this.runListTime = v.data.list
                        this.allListTime = v.data.list
                        this.param.time = Date.parse(dateTime)
                    } else {
                        this.allListTime = this.allListTime.concat(v.data.list)
                    }
                } else if (i === 0 && index === 0) {
                    verify = false
                    this.streamOpt.vod = this.streamOpt.vod ? 0 : 1
                }
            })
            if(verify || i === 1){
                this.shiftingTime = 0
                this.loading = false
                if (this.picker) {
                    this.picker.selectDate(this.param.time, {updateTime: true});
                    this.picker.setViewDate(this.param.time);
                }
                // 是否触发听见方法
                if(isEmit){
                    this.emitter.emit('vod-end')
                }
                // 数据为空时也返回错误
                if(res[0].data?.url){
                    this.isTip && this.showStorageLocation()
                    return res[0].data
                } else {
                    Promise.reject(res)
                }
            }
        }
    }

    private cleanTip = () => {
      if (!this.recordTip) { return }
        const recordDiv: any = this.el.querySelector(
            "." + prefixName + "-record-text"
        );
        recordDiv.style.display = "none";
        clearTimeout(this.recordTip);
        this.recordTip = null;
    };

    showStorageLocation(){
        this.cleanTip()
        const recordDiv: any = this.el.querySelector(
            "." + prefixName + "-record-text"
        );
        recordDiv.innerHTML = this.streamOpt.vod === 0 ? "中心存储" : "前端存储";
        recordDiv.style.display = "block";
        this.recordTip = window.setTimeout(() => {
            recordDiv.style.display = "none";
        }, 10000);
    }

    // 设置时间轴
    timeBarAnimation(osdtime:string) {
        if (this.loading || !this.timeline) {
            return
        }
        const {runListTime} = this
        const currentTime = parseInt(osdtime) - new Date().getTimezoneOffset() * 60 * 1000.04 - (3600000 * 8)
        const timestamp = this.param.time + currentTime + this.shiftingTime
        runListTime.forEach((v, index: number) => {
            const begin = Date.parse(format(v.endTime, 'YYYY-MM-DD HH:mm:ss'))
            if (runListTime.length - 1 === index && begin + 60 === timestamp) {
                this.queryRecord({dateTime: format(timestamp, 'YYYY-MM-DD HH:mm')} as any)
            }
            // 判断是否在片段的空白时间
            if (runListTime.length - 1 > index) {
                const end = Date.parse(format(runListTime[index + 1].beginTime, 'YYYY-MM-DD HH:mm:ss'))
                if (begin < timestamp + 1 && timestamp < end) {
                    this.shiftingTime += end - begin
                }
            }
        })
        this.timeline.setTimeMove({timestamp: timestamp, direction: true})
        // console.log(format(timestamp,'YYYY-MM-DD HH:mm:ss'))
        // 设置时间器时间
        if(!this.picker.visible){
            this.picker.selectDate(timestamp, {updateTime: true});
            this.picker.setViewDate(timestamp);
        }
    }

    // 销毁
    destroy(){
        this.cleanTip()
        // 时间轴
        if(this.timeline){
            this.timeline.clear()
            this.timeline = null
        }
        // 监听
        if(this.process){
            this.process.removeEventListener("click", this.setStopPropagation,false)
            this.process = null
            this.setTimelineEvent(false)
        }
        // 日期选择器
        if(this.picker){
            this.picker.$datepicker.removeEventListener("click", this.setStopPropagation,false)
            this.picker.destroy()
            this.picker = null;
        }
        // emitter
        if(this.emitter){
            this.emitter.removeAllListeners()
            this.emitter = null;
        }
    }
}

export default vodPlayer
