/**
 * Klasse einer einzelnen Tafel
 *
 * 1.1.1    2023-08-04  Markus Ehring
 *          -neues Feature: Parameter zum erzwingen eines Zeilen-/Spaltenbruchs beim Hinzufuegen einer neuen Box wird bei der ersten Box auf "false" erzwungen
 *          -BugFix: lange Whiteboardtitel ueberlappen nicht mehr Logo vom InfoPanelknopf
 *
 * @constructor
 * @param pTitle {String} Titel der Tafel
 * @param pNavigationTitle {String} Zweiter Titel
 * @param pAnordnung {"spaltenweise", "zeilenweise"} Anordnung der Boxen
 */
function Board(pAnordnung) {
    this.pTitle = "Title";
    this.pNavigationTitle = "navigation Title";
    this.pAnordnung = pAnordnung;
    this.rFrames = [];
    this.pBoxMaxWidth = 0;
    this.pBoxCurrentWidth = 0;
    this.pBoxMaxHeight = 0;
    this.pBoxCurrentHeight = 0;
    this.rObjects = [];
    this.pJsonId = newJsonId();
    this.pCanvasVisible = true;
    this.pForceResetBtn = false;
    this.boxes = 0;

    /**
     * Fuegt dem Board ein HTML Element hinzu
     * @param {*} pHtml neues Element für die Tafel
     */
    this.addElement = function (pHtml) {
        this.rDiv.append(pHtml);
    };

    /**
     * Fuegt eine neue Box zu der Tafel hinzu
     * @param {float} pWidth Breite
     * @param {float} pHeight
     * @param {boolean} pBreaking
     * @returns das neue Box Element
     */
    this.addBox = function (pWidth, pHeight, pBreaking) {
        this.boxes += 1;
        var newBox = new Box(pWidth, pHeight, pBreaking);
        newBox.pBoardId = this.pBoardId;
        if (pBreaking && this.boxes > 1) {
            this.addElement('<div class="break"></div>');

            // manage current dimensions for linebreaks
            if (this.pAnordnung == "zeilenweise") {
                this.pBoxMaxWidth = Math.max(this.pBoxCurrentWidth, this.pBoxMaxWidth);
                this.pBoxCurrentWidth = 0;
                this.pBoxMaxHeight += this.pBoxCurrentHeight;
                this.pBoxCurrentHeight = 0;
            } else if (this.pAnordnung == "spaltenweise") {
                this.pBoxMaxHeight = Math.max(this.pBoxCurrentHeight, this.pBoxMaxHeight);
                this.pBoxCurrentHeight = 0;
                this.pBoxMaxWidth += this.pBoxCurrentWidth;
                this.pBoxCurrentWidth = 0;
            }
        } else pBreaking = false;

        // manage dimensions for new boxes
        if (this.pAnordnung == "zeilenweise") {
            this.pBoxCurrentWidth += pWidth;
            this.pBoxMaxWidth = Math.max(this.pBoxCurrentWidth, this.pBoxMaxWidth);
            this.pBoxCurrentHeight = Math.max(this.pBoxCurrentHeight, pHeight);
        } else if (this.pAnordnung == "spaltenweise") {
            this.pBoxCurrentHeight += pHeight;
            this.pBoxMaxHeight = Math.max(this.pBoxCurrentHeight, this.pBoxMaxHeight);
            this.pBoxCurrentWidth = Math.max(this.pBoxCurrentWidth, pWidth);
        }

        //console.log(this.navigationTitle + ": " + this.getBoxWidth() + ", " + this.getBoxHeight());

        // add element in div
        newBox.pId = this.pId + "_" + this.rObjects.length;
        // newBox.rSelector = $('<div class="box" id="box_' + newBox.pId + '">Box ' + pWidth + " " + pHeight + " " + pBreaking + "</div>").appendTo(this.rDiv);
        newBox.rSelector = $('<div class="box" id="box_' + newBox.pId + '">' + "</div>").appendTo(this.rDiv);
        makeUnselectable(newBox.rSelector);

        $(this.rDiv)
            .children(".box")
            .last()
            .css("width", pWidth + "px");
        $(this.rDiv)
            .children(".box")
            .last()
            .css("height", pHeight + "px");
        // save initial proportions without units
        $(this.rDiv).children(".box").last().attr("pInitialWidth", pWidth);
        $(this.rDiv).children(".box").last().attr("pInitialHeight", pHeight);
        //return $(this.rDiv).children(".box").last();

        newBox.rParent = this.rDiv;
        this.rObjects.push(newBox);
        this.resize();
        return newBox;
    };

    /**
     *
     * @returns Breite aller Boxen zusammen
     */
    this.getBoxWidth = function () {
        if (this.pAnordnung == "spaltenweise") {
            return this.pBoxMaxWidth + this.pBoxCurrentWidth;
        } else {
            return this.pBoxMaxWidth;
        }
    };

    /**
     *
     * @returns Hoehe aller Boxen zusammen
     */
    this.getBoxHeight = function () {
        if (this.pAnordnung == "zeilenweise") {
            return this.pBoxMaxHeight + this.pBoxCurrentHeight;
        } else {
            return this.pBoxMaxHeight;
        }
    };

    /**
     * Fuegt der Tafel ein neues Objekt hinzu
     * @param {*} rObj hinzuzufuegende Objekt
     */
    this.addObject = function (rObj) {
        this.rObjects.push(rObj);
        this.rObjects[this.rObjects.length - 1].pBoardId = this.pBoardId;
        this.rObjects[this.rObjects.length - 1].create(this.rDiv);
    };

    /**
     * Berechnet die Skalierung aller Elemente der Tafel neu
     */
    this.resize = function () {
        // scale each box according to maximum possible scale
        if (true) {
            var contentWidth = $(this.rCanvas).width();
            var contentHeight = $(this.rCanvas).height();
            var scaleX = contentWidth / this.getBoxWidth();
            var scaleY = contentHeight / this.getBoxHeight();
            this.pScale = Math.min(scaleX, scaleY);
            //console.log("scale(" + scaleX + ", " + scaleY + ")");
            for (let i = 0; i < this.rObjects.length; i++) {
                this.rObjects[i].setScale(this.pScale);
            }

            // adjust title size
            $("#boardTitle_1_home").css("font-size", "3vh");

            // meist linke Position aller Elemente des Infoknopfes bekommen
            var btn_info_left = $("#btn_info").offset().left;
            $("#btn_info")
                .children()
                .each(function () {
                    btn_info_left = Math.min(btn_info_left, $(this).offset().left);
                });
            var correction = 0.9;
            while ($("#boardTitle_1_home").width() + $("#boardTitle_1_home").offset().left > btn_info_left) {
                $("#boardTitle_1_home").css("font-size", parseFloat($("#boardTitle_1_home").css("font-size")) * correction);
            }
            $("#boardTitle_1_board").css("font-size", "3.5vh");
            while ($("#boardTitle_1_board").width() + $("#boardTitle_1_board").offset().left > btn_info_left) {
                $("#boardTitle_1_board").css("font-size", parseFloat($("#boardTitle_1_board").css("font-size")) * correction);
            }
            $("#boardTitle_2_home").css("font-size", "7.5vh");
            while ($("#boardTitle_2_home").width() + $("#boardTitle_2_home").offset().left > btn_info_left) {
                $("#boardTitle_2_home").css("font-size", parseFloat($("#boardTitle_2_home").css("font-size")) * correction);
            }
            $("#boardTitle_2_board").css("font-size", "3.5vh");
            while ($("#boardTitle_2_board").width() + $("#boardTitle_2_board").offset().left > btn_info_left) {
                $("#boardTitle_2_board").css("font-size", parseFloat($("#boardTitle_2_board").css("font-size")) * correction);
            }
        }
    };

    /**
     * Loest alle loesbaren interaktiven Elemente
     */
    this.solve = function () {
        for (let i = 0; i < this.rObjects.length; i++) {
            this.rObjects[i].solve();
        }
    };

    /**
     * Loesungsstatus alles interaktiven Elemente
     * @returns {boolean} True falls alle Elemente der Tafel geloest sind. Sonst False
     */
    this.isSolved = function () {
        var s = true;
        for (let i = 0; i < this.rObjects.length; i++) {
            if (!this.rObjects[i].isSolved()) {
                s = false;
            }
        }
        return s;
    };

    /**
     * Setzt alle Elemente der Tafel in ihren Ausgangszustand zurück
     */
    this.reset = function () {
        for (let i = 0; i < this.rObjects.length; i++) {
            this.rObjects[i].reset();
        }
    };

    /**
     * ALT RECHTSCHREIBFEHLER
     * Registriert ein neues loesbares interaktives Objekt
     * @param {*} rObj loesbares Objekt
     */
    this.addSolvabel = function (rObj) {
        return this.addSolvable(rObj);
    };

    /**
     * Registriert ein neues loesbares interaktives Objekt
     * @param {*} rObj loesbares Objekt
     */
    this.addSolvable = function (rObj) {
        //<button class="btn_bottom" type="button" id="btn_reset" onclick="reset()">RESET</button>
        //<button class="btn_bottom" type="button" id="btn_solve" onclick="solve()">SOLVE</button>
        this.forceResetBtn();
        var solve = $(`<button class="btn_bottom btn_solve shadow" type="button" id="btn_solve_${rObj.pJsonId}" title="Lösen"></button>`).appendTo(this.rButtons);

        solve.click(function (e) {
            rObj.solve();
        });
        var reset = $(`<button class="btn_bottom btn_reset shadow" type="button" id="btn_reset_${rObj.pJsonId}" title="Zurücksetzen"></button>`).appendTo(this.rButtons);
        reset.click(function (e) {
            rObj.reset();
        });
        reset.hide();

        // TODO ICONS
        reset.css("background-image", 'url("src/icons/TB_Puzzle-zuruecksetzen_BL.svg")');
        solve.css("background-image", 'url("src/icons/TB_Puzzle-loesen_BL.svg")');

        if ($(this.rButtons).children().length == 4) {
            $(this.rSolveBtn).hide();
            // if (!this.pForceResetBtn) {
            //     $(this.rResetBtn).hide();
            // }
        } else {
            $(this.rButtons)
                .children()
                .each(function (i) {
                    $(this).show();
                });
        }

        // reset.hide();

        return { solve: solve, reset: reset };
    };

    this.forceResetBtn = function () {
        $(this.rResetBtn).show();
        this.pForceResetBtn = true;
        // console.log("forceResetBtn" + this.pId);
    };

    /**
     * Generiert eine JSON Repraesentation der Tafel
     * @returns {JSON} board
     */
    this.export = function () {
        var board = {
            pJsonId: this.pJsonId,
            rObjects: [],
            rCanvas: "test",
            rCanvasVisible: this.pCanvasVisible,
        };

        for (let i = 0; i < this.rObjects.length; i++) {
            board.rObjects.push(this.rObjects[i].export());
        }

        var canvasAsText = document.querySelector("#" + $(this.rCanvas).attr("id")).toDataURL(1);
        board.rCanvas = String(canvasAsText);

        return board;
    };

    /**
     * Importiert den Zustand eines JSON Elements
     * @param {JSON} rObj Zustand in JSON Element
     */
    this.import = function (rObj) {
        for (let i = 0; i < rObj.rObjects.length; i++) {
            for (let j = 0; j < this.rObjects.length; j++) {
                if (this.rObjects[i] != null && rObj.rObjects[i] != null) {
                    if (this.rObjects[i].pJsonId == rObj.rObjects[i].pJsonId) {
                        this.rObjects[i].import(rObj.rObjects[i]);
                    }
                } else {
                    // console.log(this.rObjects[i].pJsonId);
                }
            }
        }

        var img = new Image();
        var t = this;
        img.onload = function () {
            var canvas = document.querySelector("#" + $(t.rCanvas).attr("id"));
            var ctx = canvas.getContext("2d");
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.drawImage(img, 0, 0);
        };
        img.src = rObj.rCanvas;

        //$(t.rCanvas).appendTo(this.rDiv);
        $(t.rDiv).append(t.rCanvas);

        if (rObj.rCanvasVisible) {
            $(this.rCanvas).show();
        } else {
            $(this.rCanvas).hide();
        }
    };

    /**
     *
     * @param {String} pTitle - Titel der Tafel
     */
    this.setTitle = function (pTitle) {
        this.pTitle = pTitle;
    };

    /**
     *
     * @param {String} pNavigationTitle - Titel der Tafel im Navigationsmenue
     */
    this.setNavigationTitle = function (pNavigationTitle) {
        this.pNavigationTitle = pNavigationTitle;
    };

    /**
     *
     * @param {String} pInfo - Infotext der Tafel
     */
    this.setInfo = function (pInfo) {
        this.pInfoText = pInfo;
        this.rInfo = $('<div class="infoText"></div>').appendTo("#info_panel_page");
        if (this.pId == 0) {
            $(this.rInfo).html("<b>" + this.pTitle + "</b><br>" + pInfo);
        } else {
            $(this.rInfo).html("<b>Tafel " + this.pId + ": " + this.pTitle + "</b><br>" + pInfo);
        }
    };
}
