import {FlashMessenger, Helper, Menu, MenuAction, SystemSettings} from "../../../../../js/lib/pwa-lib";
import {TemplateContainer} from "../wordrotator/Segment/TemplateContainer";
import {LevelHelper} from "../wordrotator/Level/LevelHelper";
import {WordRotatorDb} from "../WordRotatorDb";
import {Matomo, ScaleHelper, SoundManager} from "../../../../../js/lib/pwa-assets";
import {EndSite} from "./EndSite";
import {WordRotatorBaseSite} from "./WordRotatorBaseSite";
import {SettingsManager} from "../../../../../js/lib/pwa-core";

export class LevelSite extends WordRotatorBaseSite {
    constructor(siteManager) {
        super(siteManager, "html/application/level.html");
    }

    createActionBarMenu(menu) {
        menu = super.createActionBarMenu(menu);

        let coinAction = new MenuAction(Helper.nonNull(localStorage.getItem("coins"), "0"), () => {
        }, MenuAction.SHOW_ALWAYS, 900);
        coinAction.setShouldTranslate(false);
        coinAction._liClass = "coin-counter";
        menu.addAction(coinAction);
        this.coinAction = coinAction;

        return menu;
    }

    onConstruct(args) {
        this.levelCounter = Helper.nonNull(localStorage.getItem("levelCounter"), 1);
        this.levelScaler = () => {
        };
        this.wonParams = {
            aborted: false,
            coinCounterTimer: null,
        };
        this.coinPromise = Promise.resolve();

        let settingsManager = SettingsManager.getInstance();
        let soundManager = SoundManager.getInstance();
        soundManager.set({
            audio: "sound/single_coin_fall_on_concrete_.mp3",
            muted: (settingsManager.getSetting("play-sound", "1") !== "1"),
            volume: 0.7
        }, SoundManager.CHANNELS.SOUND);

        soundManager.resume(SoundManager.CHANNELS.MUSIC);

        return super.onConstruct(args);
    }

    async onFirstStart() {
        super.onFirstStart();
        let leafSegmentTemplate = this.findBy("#segment-leaf-template");
        let parentSegmentTemplate = this.findBy("#segment-parent-template");
        let rowSegmentTemplate = this.findBy("#segment-row-template");
        let triangleTemplate = this.findBy("#segment-triangle-template");

        leafSegmentTemplate.id = null;
        parentSegmentTemplate.id = null;
        rowSegmentTemplate.id = null;
        triangleTemplate.id = null;

        leafSegmentTemplate.remove();
        parentSegmentTemplate.remove();
        rowSegmentTemplate.remove();
        triangleTemplate.remove();

        let self = this;
        let continueButton = this.findBy("#continue-button");
        continueButton.addEventListener("click", () => {
            self.nextLevel();
        });

        let wonText = this.findBy("#won-text");

        let scaleHelper = new ScaleHelper();
        this.continueButtonScaler = await scaleHelper.scaleToFull(continueButton, continueButton.parentElement, false, true, 2);
        this.wonTextScaler = await scaleHelper.scaleToFull(wonText, wonText.parentElement, false, false, 2, null, 5);
        this.wonText = wonText;
        this.wonText.style.fontSize = "0";

        //Benutze Document, da Element außerhalb von Seite (eigentlich unschön!)
        this.levelCounterActionContainer = document.getElementById("level-number-container");
        this.levelCounterAction = document.getElementById("level-number");
        this.levelCounterAction.innerText = this.levelCounter;
        this.levelNumberScaler = await scaleHelper.scaleToFull(this.levelCounterAction, this.levelCounterActionContainer, false, false, 4);
        this.levelCounterActionContainer.classList.add("visible");
        this.templateContainer = new TemplateContainer(leafSegmentTemplate, parentSegmentTemplate, rowSegmentTemplate, triangleTemplate);

        this.coinTemplate = this.findBy("#coin-template");
        this.coinContainer = this.findBy("#coin-container");

        this.coinTemplate.id = null;
        this.coinContainer.removeAllChildren();

        this.findBy("#help-button").addEventListener("click", () => {
            this.help();
        });
        await this.loadLastLevel();
    }

    async loadLastLevel() {
        try {
            let currentLevelInfo = localStorage.getItem("currentLevel");
            if (Helper.isNotNull(currentLevelInfo)) {
                currentLevelInfo = JSON.parse(currentLevelInfo);

                const db = WordRotatorDb.getInstance();
                const levelJson = await db.loadLevel(currentLevelInfo["id"]);

                if (levelJson === null) {
                    return this.nextLevel();
                }

                const level = LevelHelper.inflateLevel(levelJson, this.templateContainer);
                level.setStartRotations(currentLevelInfo["rotations"]);

                const self = this;
                level.getWonPromise().then(() => {
                    self.levelWon(level);
                });

                level.createSegments();
                level.setLocks(currentLevelInfo["locks"]);
                level.getRootSegment()._updateElement();

                level.saveAsCurrentLevel();

                let levelSegment = this.findBy("#level");
                levelSegment.removeAllChildren().appendChild(level.getRootSegment().getElement());
                let scaleHelper = new ScaleHelper();
                this.levelScaler = await scaleHelper.scaleToFull(levelSegment, levelSegment.parentElement, false, false, 1, level.words[0].length * 1.5, null, 0);

                this.level = level;
                let res = this.tutorial();
                Matomo.push(["trackEvent", "LevelSite", "LoadLastLevel"]);
                this.level.checkHasWon();
                return res;
            }
        }
        catch (e) {
            console.error(e);
        }
        return this.nextLevel();
    }

    async nextLevel() {
        try {
            this._siteContent.classList.remove('won');
            this.wonText.style.fontSize = "0";

            const db = WordRotatorDb.getInstance();
            const nextLevelJson = await db.loadNextLevel(LevelSite.RENDERER_TYPES);

                console.log("nextLevelJson", nextLevelJson);
            if (nextLevelJson === null) {
                this.startSite(EndSite);
                this.finish();
                return;
            }
            const level = LevelHelper.inflateLevel(nextLevelJson, this.templateContainer);
            const self = this;
            level.getWonPromise().then(() => {
                self.levelWon(level);
            });

            level.createSegments();
            level.getRootSegment()._updateElement();

            level.saveAsCurrentLevel();

            let levelSegment = this.findBy("#level");
            levelSegment.removeAllChildren().appendChild(level.getRootSegment().getElement());
            let scaleHelper = new ScaleHelper();
            this.levelScaler = await scaleHelper.scaleToFull(levelSegment, levelSegment.parentElement, false, false, 1, level.words[0].length * 1.5, null, 0);

            this.level = level;
            this.levelCounterAction.innerText = this.levelCounter;
            this.levelNumberScaler();

            this.coinAction.setTitle(Helper.nonNull(localStorage.getItem("coins"), "0"));
            this.coinAction.redraw();

            this.wonParams.aborted = true;
            clearTimeout(this.wonParams.coinCounterTimer);

            Matomo.push(["trackEvent", "LevelSite", "NextLevel", "Level Number Normal", this.levelCounter]);

            this.level.checkHasWon();

            return this.tutorial();
        }
        catch (e) {
            console.log("Fehler!");
            console.error(e);
        }
    }

    onStart(args) {
        Matomo.update("Level Site");
        let res = super.onStart(args);

        if (this.levelCounterAction) {

            this.levelCounterAction.innerText = this.levelCounter;
            this.levelCounterActionContainer.classList.add("visible");
        }
        this.levelScaler();

        let settingsManager = SettingsManager.getInstance();
        let soundManager = SoundManager.getInstance();
        soundManager.set({
            audio: "sound/single_coin_fall_on_concrete_.mp3",
            muted: (settingsManager.getSetting("play-sound", "1") !== "1"),
            volume: 0.7
        }, SoundManager.CHANNELS.SOUND);

        return res;
    }

    onPause(args) {
        super.onPause(args);
        this.levelCounterActionContainer.classList.remove("visible");
    }

    async levelWon(level) {
        try {
            const db = WordRotatorDb.getInstance();
            const savePromise = db.saveLevelPlayed(level.getId());

            this.levelCounter++;
            localStorage.setItem("levelCounter", this.levelCounter);

            this._siteContent.classList.add('won');
            localStorage.removeItem("currentLevel");

            let continueButton = this.findBy("#continue-button");
            continueButton.style.transition = "none";
            continueButton.style.opacity = 0;

            this.coinContainer.removeAllChildren();
            let coinsPerLevel = SystemSettings.get("coinsPerLevel", 5);

            let coinsBefore = 0;

            let soundManager = SoundManager.getInstance();
            let audioOptions = soundManager.get(SoundManager.CHANNELS.SOUND);

            this.coinPromise = this.coinPromise.then(() => {
                coinsBefore = parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"));
                localStorage.setItem("coins", coinsBefore + parseInt(coinsPerLevel));
            }).then(() => {
                return Promise.all([new Promise((r) => {
                    setTimeout(() => {
                        r(continueButton.fadeIn());
                    }, 500)
                }), audioOptions.loadedPromise.catch(e => {
                    console.error(e)
                })]);
            });

            this.wonParams.aborted = false;

            for (let i = 0; i < coinsPerLevel; i++) {
                let coinElem = Helper.cloneNode(this.coinTemplate);
                this.coinContainer.appendChild(coinElem);
                this.coinPromise = this.coinPromise.then(() => {
                    return new Promise(r => {
                        let timeout = 350;
                        if (!this.wonParams.aborted) {
                            coinElem.fadeIn(timeout / 1000);
                            soundManager.play(SoundManager.CHANNELS.SOUND);

                            this.wonParams.coinCounterTimer = setTimeout(() => {
                                if (!this.wonParams.aborted) {
                                    this.coinAction.setTitle(++coinsBefore);
                                    this.coinAction.redraw();
                                }
                            }, timeout / 2);
                        }
                        else {
                            r();
                        }
                        //Always do the next promise for garbage collection
                        setTimeout(r, timeout);
                    })
                });
            }

            this.coinPromise = this.coinPromise.catch((e) => {
                console.error(e)
            });

            this.wonTextScaler();
            this.continueButtonScaler();
            this.levelScaler();

            Matomo.push(["trackEvent", "LevelSite", "LevelWon", "Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]);

            await savePromise;
        }
        catch (e) {
            console.error(e);
        }
    }

    help() {
        let cost = SystemSettings.get("costForHelp", 25);
        let currentCoins = parseInt(Helper.nonNull(localStorage.getItem("coins"), 0));

        if (currentCoins >= cost) {
            currentCoins -= cost;
            localStorage.setItem("coins", currentCoins);
            this.coinAction.title = currentCoins;
            this.coinAction.redraw();

            let rotatables = this.level.getRotatableSegments();
            rotatables = rotatables.filter((segment) => {
                return (!segment.isSolved(false));
            });

            let index = Math.floor(Math.random() * rotatables.length);

            let segmentToHelp = rotatables[index];
            while (segmentToHelp.rotation !== 0) {
                segmentToHelp.rotate();
            }
            segmentToHelp.setIsRotatable(false);
            this.level.saveAsCurrentLevel();

            Matomo.push(["trackEvent", "LevelSite", "Help", "Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]);
        }
        else {
            FlashMessenger.addMessage("not-enough-coins");
            Matomo.push(["trackEvent", "LevelSite", "Help", "Not enough Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]);
        }
    }

    async tutorial() {
        if (this.level.id === LevelSite.TUTORIAL.FIRST_LEVEL) {
            let currentStep = Helper.nonNull(localStorage.getItem("tutorial-step"), "1");

            let scaleHelper = new ScaleHelper();
            this._siteContent.classList.add("tutorial");
            this._siteContent.classList.add("step-" + currentStep);

            switch (currentStep) {
                case "1": {
                    this.level.setSegmentClickedListener(() => {
                        this._siteContent.classList.remove("step-1");
                        localStorage.setItem("tutorial-step", "2");
                        this.tutorial();
                    });

                    let textElem = this.findBy(".tutorial-text .step-1");

                    await this.levelScaler();
                    scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, 1, 2);

                    break;
                }
                case "2": {
                    this.level.setSegmentClickedListener(() => {
                    });
                    this.level.getWonPromise().then(() => {
                        this._siteContent.classList.remove("tutorial");
                        this._siteContent.classList.remove("step-2");
                        localStorage.removeItem("tutorial-step");
                        this.coinPromise = this.coinPromise.then(() => {
                            FlashMessenger.addMessage("extra-coins-after-first-level");
                            localStorage.setItem("coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0")) + 50);
                            this.coinAction.setTitle(Helper.nonNull(localStorage.getItem("coins"), "0"));
                            this.coinAction.redraw();
                        });
                        // this.levelScaler();
                    });

                    let textElem = this.findBy(".tutorial-text .step-2");

                    await this.levelScaler();
                    scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, 1, 2);

                    break;
                }
                default:{
                    this._siteContent.classList.remove("tutorial");
                }
            }
        }
        else if (this.level.id === LevelSite.TUTORIAL.SECOND_LEVEL) {
            let currentStep = Helper.nonNull(localStorage.getItem("tutorial-step"), "3");

            switch (currentStep) {
                case "3": {
                    let scaleHelper = new ScaleHelper();

                    this._siteContent.classList.add("tutorial");
                    this._siteContent.classList.add("step-" + currentStep);

                    let eventListener = () => {
                        this._siteContent.classList.remove("tutorial");
                        this._siteContent.classList.remove("step-3");
                        localStorage.setItem("tutorial-step", "4");
                        this.findBy("#help-button").removeEventListener("click", eventListener);
                        this.levelScaler();
                    };
                    this.findBy("#help-button").addEventListener("click", eventListener);

                    let textElem = this.findBy(".tutorial-text .step-3");

                    await this.levelScaler();
                    scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, 1, 2);
                    break;
                }
                default:{
                    this._siteContent.classList.remove("tutorial");
                }
            }
        }
        else if (this.level.id === LevelSite.TUTORIAL.BIG_SEGMENT_LEVEL) {
            let currentStep = Helper.nonNull(localStorage.getItem("tutorial-step"), "4");

            switch (currentStep) {
                case "4": {

                    let scaleHelper = new ScaleHelper();
                    this._siteContent.classList.add("tutorial");
                    this._siteContent.classList.add("step-" + currentStep);

                    let rotatableSegments = this.level.getRotatableSegments();
                    let firstSegment = rotatableSegments[0];

                    let pointer = this.findBy("#tutorial-pointer");
                    pointer.remove();
                    firstSegment.element.appendChild(pointer);

                    this.level.setSegmentClickedListener((segment) => {
                        if (firstSegment === segment) {
                            this._siteContent.classList.remove("tutorial");
                            this._siteContent.classList.remove("step-4");
                            localStorage.setItem("tutorial-step", "5");
                            this.levelScaler();
                        }
                    });

                    let textElem = this.findBy(".tutorial-text .step-4");

                    await this.levelScaler();
                    scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, 1, 2);

                    break;
                }
                default:{
                    this._siteContent.classList.remove("tutorial");
                }
            }
        }
    }
}
LevelSite.RENDERER_TYPES = [20, 40, 60, 100, 120, 140, 160];
LevelSite.TUTORIAL = {
    FIRST_LEVEL: 67,
    SECOND_LEVEL: 15,
    BIG_SEGMENT_LEVEL: 341
};