import { _decorator, Button, ccenum, Color, Component, Node, Sprite, Tween, tween, Vec3 } from 'cc';
import { LevelPage, LevelPageType } from './LevelPage';
import { LevelPanel } from '../../UI/global/LevelPanel';
import { UITweener } from '../utils/UITweener';
const { ccclass, property } = _decorator;

export enum SLIDE_STATE
{
    RIGHTSLIDE = 0,
    LEFTSLIDE = 1,
}
ccenum(SLIDE_STATE);

@ccclass('LevelPageNavigator')
export class LevelPageNavigator extends Component 
{
    @property({type: [LevelPage]})
    private updatedLevelPages: LevelPage[] = [];

    @property({type: Button})
    private prevLevelBtn: Button;

    @property({type: Sprite})
    private prevLevelBtnSprite: Sprite;

    @property({type: Button})
    private nextLevelBtn: Button;

    @property({type: Sprite})
    private nextLevelBtnSprite: Sprite;

    @property({type: Color})
    private originalBtnColor: Color;

    @property({type: Color})
    private grayedBtnColor: Color;

    @property({type: Number})
    private pageDelay: number = 0.5;

    private cachedLevelPages: LevelPage[] = [];

    public pageToHide: LevelPage;
    public currentMiddlePage: LevelPage;
    public nextPageToShow: LevelPage;

    private slideState: SLIDE_STATE;

    private pagesCount: number;
    private middlePageIndex: number = 1;
    // private nextPageNumber: number = 0;
    private levelPanel: LevelPanel;

    private pageTweener: UITweener;

    private manualPageNavigation: boolean = false;

    private lhsPagePosX: number;
    private shownPagePosX: number;
    private rhsPagePosX: number;

    public get ManualPageNaviation() : boolean
    {
        return this.manualPageNavigation;
    }

    public fn_Init(levelPanel: LevelPanel): void 
    {
        this.levelPanel = levelPanel;
        this.pagesCount = this.updatedLevelPages.length;

        this.pageToHide = this.updatedLevelPages[this.middlePageIndex - 1];
        this.currentMiddlePage = this.updatedLevelPages[this.middlePageIndex];
        this.nextPageToShow = this.updatedLevelPages[this.middlePageIndex + 1];

        this.lhsPagePosX = this.pageToHide.node.position.x;
        this.shownPagePosX = this.currentMiddlePage.node.position.x;
        this.rhsPagePosX = this.nextPageToShow.node.position.x;

        // this.slideState = SLIDE_STATE.LEFTSLIDE;
        this.manualPageNavigation = false;

        this.pageTweener = new UITweener();
    }
    
    protected onEnable(): void 
    {
        this.nextLevelBtn.node.on(Button.EventType.CLICK, () => 
        {
            this.fn_SetManualNavigation(false)
            this.fn_OnNextPageClicked();
        });
        this.prevLevelBtn.node.on(Button.EventType.CLICK, () => this.fn_SetManualNavigation(false));
        
        this.fn_SetLevelNavigationButtonColors();    
        this.ToggleInteractableForLevelBtn(SLIDE_STATE.RIGHTSLIDE);
        this.ToggleInteractableForLevelBtn(SLIDE_STATE.LEFTSLIDE);
    }
    
    protected onDisable(): void 
    {
        this.nextLevelBtn.node.off(Button.EventType.CLICK);
        this.prevLevelBtn.node.off(Button.EventType.CLICK);
    }

    private fn_SetLevelNavigationButtonColors() 
    {
        this.nextLevelBtnSprite.color = this.levelPanel.CanSlideRight ? this.originalBtnColor : this.grayedBtnColor;
        this.prevLevelBtnSprite.color = this.levelPanel.CanSlideLeft ? this.originalBtnColor : this.grayedBtnColor;
    }

    public get fn_GetPagesCount() : number 
    {
        return this.updatedLevelPages.length;
    }

    public fn_IterateAndGetLevelPage(idx: number) : LevelPage
    {
        return this.updatedLevelPages[idx];
    }

    public fn_SetManualNavigation(state: boolean)
    {
        this.manualPageNavigation = state;
    }

    public fn_OnNextPageClicked()
    {  
        if (!this.levelPanel.CanSlideRight) return;
        
        this.fn_GoForLeftSlide(true);
    }

    public fn_GoForLeftSlide(useTween: boolean) 
    {
        if (this.slideState == SLIDE_STATE.RIGHTSLIDE)
        {
            let tempData = this.nextPageToShow;
            this.nextPageToShow = this.pageToHide;
            this.pageToHide = tempData;
                
            this.nextPageToShow.node.active = true;
            this.pageToHide.node.active = false;
        }

        this.slideState = SLIDE_STATE.LEFTSLIDE;
        this.fn_SwapPositions(this.middlePageIndex + 1, this.middlePageIndex, this.middlePageIndex - 1);
        this.levelPanel.fn_UpdateNextPage();
        this.ToggleInteractableForLevelBtn(this.slideState, false);
        this.CachePositions();
        this.fn_SetLevelPagesPositions(useTween);
    }

    private fn_SwapPositions(indexA: number, indexB: number, indexC: number)
    {
        let temp = this.updatedLevelPages[indexA].pagePos;
        this.updatedLevelPages[indexA].pagePos = this.updatedLevelPages[indexB].pagePos;
        this.updatedLevelPages[indexB].pagePos = this.updatedLevelPages[indexC].pagePos;
        this.updatedLevelPages[indexC].pagePos = temp;
    }

    private CachePositions() 
    {
        let indexer = 0;
        if (this.cachedLevelPages == null)
            this.cachedLevelPages = new Array(this.pagesCount);

        this.updatedLevelPages.forEach(page => {
            this.cachedLevelPages[indexer] = page;
            this.cachedLevelPages[indexer].pageType = page.pageType;
            this.cachedLevelPages[indexer].pagePos = page.pagePos.clone();
            indexer++;
        });
    }

    private fn_UpdatePositionsViaTweenForSliding(idx: number)
    {
        let updateFunc = this.slideState == SLIDE_STATE.LEFTSLIDE ? 
                            () => this.fn_OnNextTweenUpdate() : () => this.fn_OnPrevTweenUpdate(); 

        let completeFunc = this.slideState == SLIDE_STATE.LEFTSLIDE ? 
                            () => this.fn_OnNextTweenComplete() : () => this.fn_OnPrevTweenComplete(); 

        this.pageTweener.fn_TriggerTween(
            this.updatedLevelPages[idx].node, 
            this.pageDelay, 
            this.updatedLevelPages[idx].pagePos.clone(), 
            updateFunc, 
            completeFunc);
    }

    private ToggleInteractableForLevelBtn(slidingState: SLIDE_STATE, state: boolean = true) 
    {
        if (slidingState == SLIDE_STATE.RIGHTSLIDE) {
            this.prevLevelBtn.interactable = this.levelPanel.CanSlideLeft && state;
        }
        else {
            this.nextLevelBtn.interactable = this.levelPanel.CanSlideRight && state;
        }
    }

    private fn_OnNextTweenUpdate()
    {
        this.fn_TogglePageToHide(false);
    }

    private fn_OnNextTweenComplete()
    {
        this.fn_UpdateDataOnSlideToLeft();
        this.fn_StopTween();
    }

    private fn_UpdateDataOnSlideToLeft() 
    {
        this.fn_TogglePageToHide(true);
        for (let i = 0; i < this.updatedLevelPages.length; i++) 
        {
            if (this.updatedLevelPages[i].pagePos.x == this.lhsPagePosX) {
                this.pageToHide = this.updatedLevelPages[i];
            }
            else if (this.updatedLevelPages[i].pagePos.x == this.rhsPagePosX) {
                this.nextPageToShow = this.updatedLevelPages[i];
            }
            else //if (this.updatedLevelPages[i].pagePos.x == this.shownPagePosX) 
            {
                this.currentMiddlePage = this.updatedLevelPages[i];
            }
        }

        this.ToggleInteractableForLevelBtn(this.slideState, true);
        this.ToggleInteractableForLevelBtn(SLIDE_STATE.RIGHTSLIDE, true);
        this.fn_SetLevelNavigationButtonColors();
        
        this.fn_TogglePageToHide(false);
        this.fn_ToggleMiddlePage(true);
        
    }

    private fn_StopTween() 
    {
        this.pageTweener.fn_StopTween();
    }

    public fn_OnPrevPageClicked()
    {
        if (!this.levelPanel.CanSlideLeft) return;

        this.fn_GoForRightSlide(true);
    }

    public fn_GoForRightSlide(useTween: boolean) 
    {
        if (this.slideState == SLIDE_STATE.LEFTSLIDE) {
            let tempData = this.pageToHide;
            this.pageToHide = this.nextPageToShow;
            this.nextPageToShow = tempData;

            this.nextPageToShow.node.active = true;
            this.pageToHide.node.active = false;
        }

        this.slideState = SLIDE_STATE.RIGHTSLIDE;
        this.fn_SwapPositions(this.middlePageIndex - 1, this.middlePageIndex, this.middlePageIndex + 1);
        this.levelPanel.fn_UpdatePrevPage();
        this.ToggleInteractableForLevelBtn(this.slideState, false);
        this.CachePositions();
        this.fn_SetLevelPagesPositions(useTween);
    }

    private fn_SetLevelPagesPositions(useTween: boolean) 
    {
        if (useTween) 
        {
            for (let i = 0; i < this.pagesCount; i++)
                this.fn_UpdatePositionsViaTweenForSliding(i);
        }
        else 
        {
            for (let i = 0; i < this.pagesCount; i++)
                this.fn_UpdatePositionsViaTranslation(i);
            
            if (this.slideState == SLIDE_STATE.LEFTSLIDE)
                this.fn_UpdateDataOnSlideToLeft();
            else 
                this.fn_UpdateDataOnSlideToRight();
        }
    }

    private fn_UpdatePositionsViaTranslation(idx: number)
    {
        this.fn_TogglePageToHide(false);

        this.updatedLevelPages[idx].node.active = true;
        this.updatedLevelPages[idx].node.position = this.updatedLevelPages[idx].pagePos.clone();
        this.updatedLevelPages[idx].node.active = false;
    }

    private fn_OnPrevTweenUpdate() 
    {
        this.fn_TogglePageToHide(false);
    }

    private fn_OnPrevTweenComplete() 
    {
        this.fn_UpdateDataOnSlideToRight();
        this.fn_StopTween();
    }
    
    private fn_UpdateDataOnSlideToRight() 
    {
        this.fn_TogglePageToHide(true);

        for (let i = 0; i < this.updatedLevelPages.length; i++) {
            if (this.updatedLevelPages[i].pagePos.x == this.lhsPagePosX) {
                this.nextPageToShow = this.updatedLevelPages[i];
                // console.log("PAGETOHIDE: PREV :: nextPageToShow: " + this.nextPageToShow.node.name);
            }
            else if (this.updatedLevelPages[i].pagePos.x == this.rhsPagePosX) {
                this.pageToHide = this.updatedLevelPages[i];
                // console.log("PAGETOHIDE: PREV :: pageToHide: " + this.pageToHide.node.name);
            }
            else //if (this.updatedLevelPages[i].pagePos.x == this.shownPagePosX) 
            {
                this.currentMiddlePage = this.updatedLevelPages[i];
                // console.log("PAGETOHIDE: PREV :: currentMiddlePage: " + this.currentMiddlePage.node.name);
            }
        }

        this.fn_TogglePageToHide(false);

        this.ToggleInteractableForLevelBtn(this.slideState, true);
        this.ToggleInteractableForLevelBtn(SLIDE_STATE.LEFTSLIDE, true);
        this.fn_SetLevelNavigationButtonColors();

        this.fn_ToggleMiddlePage(true);
    }

    private fn_ToggleMiddlePage(state: boolean)
    {
        // console.log("PAGETOHIDE: TOGGLE PAGE TO HIDE: " + this.pageToHide.node.name);
        this.currentMiddlePage.node.active = state;
    }

    private fn_TogglePageToHide(state: boolean)
    {
        // console.log("PAGETOHIDE: TOGGLE PAGE TO HIDE: " + this.pageToHide.node.name);
        this.pageToHide.node.active = state;
    }
}




