import {replaceContent, editor} from "./cmEditor.js";
import {
    rows,
    cols,
    drawAll,
    territoryContent,
    CellContent,
    calculateCanvasSize,
    createNewTerritoryContent, setRows, setColumns, calculateGridSize
} from "./canvas.js";
import {
    addToHamsterArray,
    clearHamsterArray,
    hamster,
    Hamster,
    hamsterCounter,
    hamsters,
    setDefaultHamster, setHamsterCounter
} from "./hamster.js";
import {closeSaveFilesDialog, errorDialogOpen, openErrorDialog} from "./dialogs.js";
import {languagesStrings, userLanguage} from "./language.js";
import {closeMenu} from "./navigation.js";

let tempTerritoryContent;
let tempHamsters = [];
let tempHamsterCounter;

/**
 * Speichert den aktuellen Zustand des Territoriums temporär.
 */
export function saveTemporaryTerritory() {
    tempHamsters = [];
    tempTerritoryContent = null;
    tempHamsterCounter = hamsterCounter;
    
    hamsters.forEach(function (hamster) {
        territoryContent[hamster.getRow()][hamster.getColumn()].removeHamster(hamster);
        tempHamsters.push(JSON.stringify(hamster));
    });
    
    tempTerritoryContent = JSON.stringify(territoryContent);
}

/**
 * Lädt den temporär gespeicherten Zustand des Territoriums.
 */
export function loadTemporaryTerritory() {
    setHamsterCounter(tempHamsterCounter);
    let newTerritoryContent = JSON.parse(tempTerritoryContent);
    copyTerritory(newTerritoryContent);
    
    clearHamsterArray();
    tempHamsters.forEach(function (currentHamster) {
        let newHamster = new Hamster(JSON.parse(currentHamster));
        if (newHamster.getName() === "hamster") {
            setDefaultHamster(newHamster);
        }
        
        addToHamsterArray(newHamster);
        territoryContent[newHamster.getRow()][newHamster.getColumn()].addHamster(newHamster);
    });
 
    drawAll();
}

/**
 * Erstellt für das Territorium neuen Zellen und fügt dort die neuen Inhalte ein.
 * 
 * @param newTerritoryContent, Inhalt des neuen Territoriums.
 */
function copyTerritory(newTerritoryContent) {
    for (let r = 0; r < rows; r++) {
        for (let c = 0; c < cols; c++) {
            territoryContent[r][c] = new CellContent(newTerritoryContent[r][c]);
        }
    }
}

/**
 * Validiert und führt den Speichervorgang für Editor- und Territoriums-Dateien durch.
 * 
 * @param event, das auslösende Event.
 */
export function validateAndSave(event) {
    event.preventDefault();

    const option = document.querySelector('input[name="save-option"]:checked');

    switch (option.id) {
        case "save-all":
            saveFile("save-editor");
            saveFile("save-territory");
            break;
        case "save-editor":
            saveFile("save-editor");
            break;
        case "save-territory":
            saveFile("save-territory");
            break;
        default:
            if (!errorDialogOpen) {
                openErrorDialog(languagesStrings[userLanguage]['error-unknown']);
            }

    }

    closeSaveFilesDialog();
    closeMenu(event);
}

/**
 * Speichert den aktuellen Zustand des Editors/Territoriums als verschlüsseltes JSON-Objekt und stellt die Datei
 * im Download des Browsers zur Verfügung.
 * 
 * @param checkboxId, ausgewählte Checkbox im Speichern-Dialog, zur Bestimmung, welche Daten gespeichert werden sollen.
 */
function saveFile(checkboxId) {
    let data = {};
    let downloadLink = document.createElement('a');
    switch (checkboxId) {
        case "save-editor":
            const editorText = editor.state.doc.toString();
            data = JSON.stringify(editorText);
            downloadLink.download = 'online-hamster-simulator.editor.json';
            break;
        case "save-territory":
            const dataObj = {
                territoryContent: territoryContent,
                hamster: hamster
            }
            data = JSON.stringify(dataObj);
            downloadLink.download = 'online-hamster-simulator.territory.json';
            break;
        default:
            if (!errorDialogOpen) {
                openErrorDialog(languagesStrings[userLanguage]['error-unknown']);
            }
            return;
    }

    let blob = new Blob([data], { type: 'application/json' });
    let blobURL = URL.createObjectURL(blob);
    
    // Download-Link erstellen und klicken
    downloadLink.href = blobURL;
    document.body.appendChild(downloadLink);
    downloadLink.click();

    // Cleanup
    URL.revokeObjectURL(blobURL);
    document.body.removeChild(downloadLink);
}

/**
 * Liest eine vom Benutzer geladene Editor-Datei und fügt den Inhalt in den TextEditor der Webseite ein.
 *
 * @param event, das auslösende Event.
 * @param file, vom Benutzer ins Programm geladene Editor-Datei.
 * @param callback, signalisiert den Erfolg bzw. Misserfolg der Funktion.
 */
export function loadCodeFile(event, file, callback) {
    const reader = new FileReader();

    reader.onloadend = async function () {
        try {
            const data = reader.result.toString();
            const code = JSON.parse(data);
            replaceContent(code);
            closeMenu(event);
            callback(true);
        } catch (err) {
            callback(false);
        }
    };

    reader.readAsText(file);
}

/**
 * Liest eine vom Benutzer geladene Territorium-Datei und zeichnet mit den entsprechenden Werten das Territorium
 * sowie den Default-Hamster neu.
 * 
 * Es wird davon ausgegangen, dass der Benutzer den Inhalt der Datei nach dem Speichern nicht verändert hat.
 * Andernfalls tritt beim Lesen der Datei ein Fehler auf.
 * 
 * @param event, das auslösende Event.
 * @param file, vom Benutzer ins Programm geladene Territorium-Datei.
 * @param callback, signalisiert den Erfolg bzw. Misserfolg der Funktion.
 */
export function loadTerritoryFile(event, file, callback) {
    const reader = new FileReader();

    reader.onloadend = async function () {
        try {
            const data = reader.result.toString();
            const dataObj = JSON.parse(data)
            const newTerritoryContent = dataObj.territoryContent;
            
            setRows(newTerritoryContent.length);
            setColumns(newTerritoryContent[0].length);
            calculateCanvasSize();
            calculateGridSize();
            createNewTerritoryContent();
            copyTerritory(newTerritoryContent);
            clearHamsterArray();
            setDefaultHamster(new Hamster(dataObj.hamster));
            addToHamsterArray(hamster);
            drawAll();
            closeMenu(event);
            callback(true);
        } catch (err) {
            callback(false);
        }
    };

    reader.readAsText(file);
}