/**
 @class ZombiepediaPanel
 @author YI ZHANG
 @date 2022/8/21
 @desc
 **/

import * as cc from "cc";
import { JSB } from "cc/env";

const {ccclass, property} = cc._decorator;

export interface ZombiepediaPanelData {
}

@ccclass("ZombiepediaPanel")
export default class ZombiepediaPanel extends cc.Component{
    @property([cc.Animation])
    pageList : cc.Animation[] = []
    @property(cc.Camera)
    pageCamera : cc.Camera = null!;
    sumPage: number = 20;
    dataList : number[] = [1,2,3,4,5,6,7,8,9];
    curPage: number = 1;
    @property(cc.Node)
    firstPageNode : cc.Node = null!;
    @property(cc.Node)
    pageNumNode : cc.Node = null!;
    @property(cc.Node)
    blockNode : cc.Node = null!;
    private leftStartX: number = 0;
    private rightStartX: number = 0;
    renderTextureList : cc.RenderTexture[] = [];
    private progress: number = 0;
    private beCreatePageList: number[] = [];


    createRenderTexture(){
        let list = this.pageList;
        for(let i = 0;i < 6;++i){
            let renderTexture = new cc.RenderTexture();

            renderTexture.initialize({
                width: 190,
                height: 256,
            });
            // @ts-ignore
            renderTexture.setFilters(cc.gfx.Filter.POINT, cc.gfx.Filter.POINT);
            let spriteFrame = new cc.SpriteFrame();
            spriteFrame.texture = renderTexture;
            list[i].getComponent(cc.Sprite)!.spriteFrame = spriteFrame;
        }
    }

    destroyRenderTexture(){
        let list = this.pageList;
        for(let i = 0;i < list.length;++i){
            let comp = list[i].getComponent(cc.Sprite)!;
            if(comp.spriteFrame){
                comp.spriteFrame!.texture.destroy();
                comp.spriteFrame!.destroy();
                comp.spriteFrame = null;
            }

        }
    }

    protected onLoad() {
        this.show({});
    }

    async show(extData: ZombiepediaPanelData) {
        this.sumPage = this.dataList.length + 2;
        if(this.sumPage % 2 == 1){
            this.sumPage++;
        }
        this.pageList[0].node.on(cc.Node.EventType.TOUCH_START, this.onLeftStartTouch, this);
        this.pageList[0].node.on(cc.Node.EventType.TOUCH_MOVE, this.onLeftMove, this);
        this.pageList[0].node.on(cc.Node.EventType.TOUCH_CANCEL, this.onLeftEnd, this);
        this.pageList[0].node.on(cc.Node.EventType.TOUCH_END, this.onLeftEnd, this);

        this.pageList[5].node.on(cc.Node.EventType.TOUCH_START, this.onRightStartTouch, this);
        this.pageList[5].node.on(cc.Node.EventType.TOUCH_MOVE, this.onRightMove, this);
        this.pageList[5].node.on(cc.Node.EventType.TOUCH_CANCEL, this.onRightEnd, this);
        this.pageList[5].node.on(cc.Node.EventType.TOUCH_END, this.onRightEnd, this);
        this.createRenderTexture();
        this.pushCreatePage(this.curPage);
        this.pushCreatePage(this.curPage + 1);
        this.pushCreatePage(this.curPage + 2);
        this.pushCreatePage(this.curPage + 3);
        this.pushCreatePage(this.curPage - 2);
        this.pushCreatePage(this.curPage - 1);
        this.blockNode.active = true;
        await new Promise((resolve)=>{
            this.createPageProcess(resolve);
            this.blockNode.active = false;
        })
        await this.reset();

    }

    close() {
        this.pageList[0].targetOff(this);
        this.pageList[5].targetOff(this);
        this.destroyRenderTexture();
    }



    reset() {
        this.setPageProgress(this.curPage,0);
        this.setPageProgress(this.curPage + 1,0);
    }

    pushCreatePage(page : number){
        this.beCreatePageList.push(page);
    }

    createPageProcess(cb : ()=>void){
        if(this.beCreatePageList.length){
            let page = this.beCreatePageList.shift()!;
            let index = page - this.curPage + 2;
            let target = this.pageList[index];
            if(page > 0 && page <= this.sumPage){
                this.pageCamera.enabled = true;
                this.pageCamera.targetTexture = target.getComponent(cc.Sprite)!.spriteFrame!.texture as cc.RenderTexture;
                this.initContent(page,()=>{
                    this.scheduleOnce(()=>{
                        if(JSB){
                            this.scheduleOnce(()=> {
                                this.scheduleOnce(()=> {
                                    this.scheduleOnce(()=> {
                                        this.createPageProcess(cb);
                                        this.pageCamera.targetTexture = null;
                                        this.pageCamera.enabled = false;
                                    },0.1);
                                });
                            });
                        }else {
                            this.createPageProcess(cb);
                            // this.pageCamera.enabled = false;

                        }

                    })
                });
            }else {
                this.createPageProcess(cb);
            }
        }else {
            this.pageCamera.targetTexture = null;
            this.pageCamera.enabled = false;
            this.pageList[0].node.setSiblingIndex(0);
            this.pageList[5].node.setSiblingIndex(1);
            this.pageList[2].node.setSiblingIndex(2);
            this.pageList[3].node.setSiblingIndex(3);
            this.pageList[1].node.setSiblingIndex(4);
            this.pageList[4].node.setSiblingIndex(5);
            cb();
        }
    }

    initContent(page : number,cb : ()=>void){
        this.pageNumNode.getComponent(cc.Label)!.string = (page).toString();
        cb();
    }



    onLeftStartTouch(event: cc.EventTouch) {
        this.leftStartX = event.getUILocation().x;
    }

    onLeftMove(event: cc.EventTouch) {
        let x = event.getUILocation().x - this.leftStartX;
        this.setPageProgress(this.curPage,x / 100);
    }

    onLeftEnd(event: cc.EventTouch) {
        let x = event.getUILocation().x - this.leftStartX;
        let progress = x / 100;
        this.leftNext(progress);

    }

    pageNext(page : number,progress: number,force : boolean = false){
        this.progress = progress;
        let isLeft = page % 2 == 1;
        let isCanNext = isLeft  ? this.isCanPre() : this.isCanNext();
        this.blockNode.active = true;
        if ((progress > 0.6 || force) && isCanNext) {
            let time = Math.max(0.01, (2 - progress) * 0.25);
            // @ts-ignore
            cc.tween(this).to(time, {progress : 2}, {
                onUpdate: () => {
                    this.setPageProgress(page,this.progress);
                }
            }).call(()=>{
                if(page % 2 == 1){
                    this.curPage -= 2;
                    let page1 = this.pageList.pop()!;
                    let page2 = this.pageList.pop()!;
                    this.pageList.unshift(page1)
                    this.pageList.unshift(page2)
                    this.pushCreatePage(this.curPage - 2);
                    this.pushCreatePage(this.curPage - 1);
                    this.createPageProcess(()=>{
                        this.reset();
                        this.blockNode.active = false;
                    })
                }else {
                    this.curPage += 2;
                    let page1 = this.pageList.shift()!;
                    let page2 = this.pageList.shift()!;
                    this.pageList.push(page1)
                    this.pageList.push(page2);
                    this.pushCreatePage(this.curPage + 2);
                    this.pushCreatePage(this.curPage + 3);
                    this.createPageProcess(()=>{
                        this.reset();
                        this.blockNode.active = false;
                    })
                }
            }).start();
        }else {
            this.progress = ZombiepediaPanel.clamp(progress,0,1);
            let time = ZombiepediaPanel.clamp(progress * 0.5,0.01,0.2)
            // @ts-ignore
            cc.tween(this).to(time, {progress: 0}, {
                onUpdate: () => {
                    this.setPageProgress(page,this.progress);
                }
            }).call(()=>{
                this.blockNode.active = false;
            }).start();
        }
    }

    static clamp(value : number,min : number, max :number){
        return value > max ? max : (value < min ? min : value);
    }

    leftNext(progress: number,force : boolean = false) {
        this.pageNext(this.curPage,progress,force);
    }

    onRightStartTouch(event: cc.EventTouch) {
        this.rightStartX = event.getUILocation().x;
    }

    onRightMove(event: cc.EventTouch) {
        let x = event.getUILocation().x - this.rightStartX;
        this.setPageProgress(this.curPage + 1,-x / 100);
    }

    onRightEnd(event: cc.EventTouch) {
        let x = event.getUILocation().x - this.rightStartX;
        let progress = -x / 100;
        this.rightNext(progress);

    }

    rightNext(progress: number,force : boolean = false) {
        this.pageNext(this.curPage + 1,progress,force);
    }

    getLerpColor(progress : number){
        progress = ZombiepediaPanel.clamp(progress,0,1)
        return cc.Color.lerp(cc.color(),cc.color("#828C96"), cc.Color.WHITE,progress);
    }

    setPageProgress(page : number,progress: number){
        let isLeft = page % 2 == 1;
        let isCanNext = isLeft  ? this.isCanPre() : this.isCanNext();
        let clip = isCanNext ? 1 : 0;
        page = page - this.curPage + 2;
        let showPage = page;
        let nextPage = isLeft ? page - 1 : page + 1;
        let bottomPage = isLeft ? page - 2 : page + 2;
        let otherShow = isLeft ? page + 1 : page - 1;
        let clip1 = this.pageList[0].clips[clip]!;
        let clip2 = this.pageList[0].clips[1]!;
        if (progress <= 1 || !isCanNext) {
            this.pageList[showPage].createState(clip1).setTime(ZombiepediaPanel.clamp(1 - progress, 0.05, 1));
            this.pageList[nextPage].createState(clip2).setTime(0);
            this.pageList[bottomPage].createState(clip2).setTime(1);
            this.pageList[bottomPage].getComponent(cc.Sprite)!.color = this.getLerpColor(isCanNext ? progress : 0);
            this.pageList[otherShow].getComponent(cc.Sprite)!.color = this.getLerpColor(1);
            this.pageList[nextPage].getComponent(cc.Sprite)!.color = this.getLerpColor(1);
        } else if (progress > 1) {
            this.pageList[bottomPage].getComponent(cc.Sprite)!.color = this.getLerpColor(1);
            this.pageList[otherShow].getComponent(cc.Sprite)!.color = this.getLerpColor(2 - progress);
            this.pageList[bottomPage].createState(clip2).setTime(1);
            this.pageList[showPage].createState(clip2).setTime(0);
            this.pageList[nextPage].createState(clip2).setTime(ZombiepediaPanel.clamp(progress - 1, 0.05, 1));
        }
        this.pageList[showPage].getState(clip1.name).sample();
        this.pageList[nextPage].getState(clip2.name).sample();
        this.pageList[bottomPage].getState(clip2.name).sample();
    }

    prePage(){
        if(this.isCanPre()){
            this.leftNext(0,true);
        }
    }

    isCanPre(){
        return this.curPage > 1;
    }
    isCanNext(){
        return this.curPage < this.sumPage - 1;
    }

    nextPage(){
        if(this.isCanNext()){
            this.rightNext(0,true);
        }
    }


    hide() {

    }
}

