import {
    addToHamsterArray,
    clearHamsterArray,
    createNewDefaultHamster,
    hamster,
    hamsters, resetHamsterCounter
} from "./hamster.js";
import {activeButton} from "./buttons.js";
import {
    closeChangeSizeDialog,
    colInput,
    createPromiseForAddGrainsDialog,
    rowInput,
    showTerritoryTooltip
} from "./dialogs.js";
import {saveTemporaryTerritory} from "./saveAndLoad";

let currentX;
let currentY;
let hamsterX, hamsterY;
let hamsterTempX, hamsterTempY;
let actorRow;
let actorColumn;
let numberOfGrains;
export let territoryContent;
let territoryWrapper;
let windowWidth;
let windowHeight;

export let canvas;
export let rows;
export let cols;
export let cellWidth = 50;
export let cellHeight = 50;
let territory;
let deleteImage = new Image();
let wallImage = new Image();
let grainImage = new Image();
let actorImage;

let isDragging = false;
let touchEnabled = true;
let offsetX, offsetY;
let offsetStartX, offsetEndX, offsetStartY, offsetEndY;
let pointerX, pointerY;
export let pointerClickX;
export let pointerClickY;
let pointerStartX, pointerEndX, pointerStartY, pointerEndY;

/**
 * Initialisiert beim Laden der Webseite die Variablen.
 */
export function loadPage() {
    windowWidth = document.body.clientWidth;
    windowHeight = document.body.clientHeight;
    canvas = document.getElementById('myCanvas');
    territory = canvas.getContext('2d');
    territoryWrapper = document.getElementById('territorium-wrapper');

    actorRow = 0;
    actorColumn = 0;
    
    rows = 9;
    cols = 10;
    numberOfGrains = 1;

    deleteImage.src = "./img/territory-buttons/delete-40x40.svg";
    wallImage.src = "./img/territory-buttons/wall-40x40.svg";
    grainImage.src = "./img/territory-buttons/corn-40x40.svg";

    currentX = 25;
    currentY = 25;
    hamsterX = 25;
    hamsterY = 25;

    window.addEventListener('resize', resizeWindow);
    calculateCanvasSize();
}

/**
 * Berechnet die Werte des Grid-Wrappers neu, wenn die Größe des Fensters verändert wird.
 */
function resizeWindow() {
    calculateGridSize();
}

/**
 * Setter für die Reihen des Territoriums
 *
 * @param value, neuer Wert.
 */
export function setRows(value) {
    rows = value;
}

/**
 * Setter für die Spalten des Territoriums
 *
 * @param value, neuer Wert.
 */
export function setColumns(value) {
    cols = value;
}

/**
 * Initialisiert beim Laden der Webseite alle Hamster mit den gewünschten Werten.
 */
export function initHamster() {
    createNewDefaultHamster();
    hamster.init(0, 0, 1, 0);
    hamster.setName("hamster");
    addToHamsterArray(hamster);
}

/**
 * Entfernt alle aktiven Hamster aus dem Territorium und platziert den Default-Hamster an seiner alten Position.
 */
export function resetHamster() {
    hamsters.forEach(function (currentHamster) {
        if (currentHamster.isInitialized()) {
            territoryContent[currentHamster.getRow()][currentHamster.getColumn()].removeHamster(currentHamster); 
        }
    });
    clearHamsterArray();
    addToHamsterArray(hamster);
    territoryContent[hamster.getRow()][hamster.getColumn()].addHamster(hamster);
    resetHamsterCounter();
    drawAll();
}

/**
 * Initialisiert beim Laden der Webseite das Canvas und seine Funktionen.
 */
export function initCanvas() {
    initTerritory();
    canvas.onpointerdown = handlePointerDownCanvas;
    canvas.onpointermove = handlePointerMoveCanvas;
    canvas.onpointerup = null;
    document.onpointerup = handlePointerUpDocument;
}

/**
 * Führt Aktionen beim Loslassen des Pointers innerhalb des Dokuments aus.
 * 
 * Überprüft, ob die Drag-und-Drop-Funktion des Canvas gerade benutzt wird und beendet diese ggf.
 * 
 * @param event, das auslösende Event.
 */
function handlePointerUpDocument(event) {
    event.preventDefault();
    
    if (isDragging) {
        let clickX = event.pageX;
        let clickY = event.pageY;
        
        if (clickX - (canvas.offsetLeft + canvas.width) <= 3 &&
            clickX - (canvas.offsetLeft + canvas.width) >= 1) {
            return;
        }
        
        if (clickX < canvas.offsetLeft ||
            clickX > canvas.offsetLeft + canvas.width ||
            clickY < canvas.offsetTop ||
            clickY > canvas.offsetTop + canvas.height &&
            getScreenWidth() > 1024) {
            canvas.onpointerup(event);
        }
    }
}

/**
 * Schaltet die Touch-Aktion für den Territoriums-Wrapper ein.
 */
export function enableTouch() {
    if (!touchEnabled) {
        territoryWrapper.style.touchAction = "auto";
        touchEnabled = true;
    }
}

/**
 * Schaltet die Touch-Aktion für den Territoriums-Wrapper aus.
 */
export function disableTouch() {
    if (touchEnabled) {
        territoryWrapper.style.touchAction = "none";
        touchEnabled = false;
    }
}

/**
 * Handelt das Verhalten, wenn der Pointer (Maus oder Touch) innerhalb des Canvas ausgeführt wird.
 * 
 * @param event, das auslösende Event.
 */
function handlePointerDownCanvas(event) {
    // Ignoriere Rechtsklick
    if (event.which === 3) {
        return;
    }
    
    event.preventDefault();
    
    // Setzt die Koordinaten des aktuellen Klicks.
    pointerClickX = event.pageX;
    pointerClickY = event.pageY;
    
    // Setzt die aktuellen Koordinaten des Klicks innerhalb des Territoriums.
    offsetX = event.pageX - canvas.offsetLeft;
    offsetY = event.pageY - canvas.offsetTop;

    let wrapper = document.getElementById('inner-wrapper');
    offsetX = offsetX + wrapper.scrollLeft;
    offsetY = offsetY + wrapper.scrollTop;
    
    // Setzt die Startkoordinaten für Drag-and-Drop.
    offsetStartX = offsetX;
    offsetStartY = offsetY;
    
    actualMousePositionToCoords(offsetX, offsetY);
    pointerStartX = pointerX;
    pointerStartY = pointerY;
    pointerEndX = pointerX;
    pointerEndY = pointerY;
    
    if (activeButton === null) {
        if (hamster.getRow() !== pointerY || hamster.getColumn() !== pointerX) {
            enableTouch();
            return;
        } else {
            hamsterTempX = hamster.getRow();
            hamsterTempY = hamster.getColumn();
            disableTouch();
        }
        
        canvas.onpointerup = handlePointerUpActor;
    } else {
        disableTouch();
        switch (activeButton.id) {
            case "info-button":
                canvas.onpointerup = handlePointerUpInfo;
                break;
            case "grain-button":
                canvas.onpointerup = handlePointerUpGrain;
                break;
            case "wall-button":
                canvas.onpointerup = handlePointerUpWall;
                break;
            case "delete-button":
                canvas.onpointerup = handlePointerUpDelete;
                break;
            default:
                return;
        }
    }
    isDragging = true;
}

/**
 * Zeigt für die ausgewählte Zelle innerhalb des Territoriums eine Infobox an.
 * 
 * @param event, das auslösende Event.
 */
function handlePointerUpInfo(event) {
    if (!isDragging) {
        return;
    }
    
    event.preventDefault();
    showCanvasInfo();
    endDragAndDrop();
}

/**
 * Aktualisiert das Territorium, beim Beenden des Drag-and-Drop-Vorgangs mit aktivierten Korn-Button.
 * 
 * @param event, das auslösende Event.
 */
async function handlePointerUpGrain(event) {
    if (!isDragging) {
        return;
    }
    
    event.preventDefault();

    // Änderung von isDragging nötig, damit der Backdrop des Dialogs funktioniert.
    isDragging = false;
    let input = await createPromiseForAddGrainsDialog();
    isDragging = true;

    if (input !== null) {
        updateTerritoryGrain(input);
    } else {
        drawAll();
    }

    endDragAndDrop();
}

/**
 * Aktualisiert das Territorium, beim Beenden des Drag-and-Drop-Vorgangs mit aktivierten Mauer-Button.
 * 
 * @param event, das auslösende Event.
 */
function handlePointerUpWall(event) {
    if (!isDragging) {
        return;
    }
    
    event.preventDefault();
    updateTerritoryWall()
    endDragAndDrop();
}

/**
 * Aktualisiert das Territorium, beim Beenden des Mauer-Drag-and-Drop-Vorgangs mit aktivierten Delete-Button.
 * 
 * @param event, das auslösende Event.
 */
function handlePointerUpDelete(event) {
    if (!isDragging) {
        return;
    }
    
    event.preventDefault();
    updateTerritoryDelete();
    endDragAndDrop();
}

/**
 * Rechnet die Position des Pointers in Koordinaten des Territoriums um.

 * @param posX -Koordinate des Pointers.
 * @param posY -Koordinate des Pointers.
 */
function actualMousePositionToCoords(posX, posY) {
    pointerX = Math.floor(posX / cellWidth);
    if (pointerX === cols) {
        pointerX = cols-1;
    } else if (pointerX < 0) {
        pointerX = 0;
    }

    pointerY = Math.floor(posY / cellHeight);
    if (pointerY === rows) {
        pointerY = rows-1;
    } else if (pointerY < 0) {
        pointerY = 0;
    }
}

/**
 * Aktualisiert die Positionswerte des Akteurs, beim Beenden des Drag-and-Drop-Vorgangs.
 * 
 * @param event, das auslösende Event.
 */
function handlePointerUpActor(event) {
    event.preventDefault();
    
    if (!isDragging) {
        return;
    }
    
    offsetX = event.pageX - canvas.offsetLeft;
    offsetY = event.pageY - canvas.offsetTop;

    let wrapper = document.getElementById('inner-wrapper');
    offsetX = offsetX + wrapper.scrollLeft;
    offsetY = offsetY + wrapper.scrollTop;

    if (territoryContent[hamster.getRow()][hamster.getColumn()].hasWall()) {
        hamster.setRow(hamsterTempX);
        hamster.setColumn(hamsterTempY);
    }

    drawAll();
    endDragAndDrop();
    enableTouch();
}

/**
 * Setzt die Werte und Methoden nach Beenden des Drag-and-Drop-Vorgangs auf default zurück.
 */
function endDragAndDrop() {
    canvas.onpointerup = null;
    isDragging = false;
}

/**
 * Berechnet den Drag-and-Drop-Bereich und führt je nach aktivierten Button unterschiedliche Aktionen aus.
 * 
 * @param event, das auslösende Event.
 */
function handlePointerMoveCanvas(event) {
    if (!isDragging) {
        return;
    }
    
    event.preventDefault();
    offsetX = event.pageX - canvas.offsetLeft;
    offsetY = event.pageY - canvas.offsetTop;

    let wrapper = document.getElementById('inner-wrapper');
    offsetX = offsetX + wrapper.scrollLeft;
    offsetY = offsetY + wrapper.scrollTop;
    
    offsetEndX = offsetX;
    offsetEndY = offsetY;
 
    actualMousePositionToCoords(offsetX, offsetY);
    
    if (activeButton === null) {
        territoryContent[hamster.getRow()][hamster.getColumn()].removeHamster(hamster);
        if (pointerY > rows-1) {
            hamster.setRow(rows-1);
        } else {
            hamster.setRow(pointerY)
        }
        
        if (pointerX > cols-1) {
            hamster.setColumn(cols-1);
        } else {
            hamster.setColumn(pointerX);
        }
        draw();
        drawTerritoryContent();
        drawHamsterTmp();
    } else {
        draw();
        drawTerritoryContent();
        switch (activeButton.id) {
            case "info-button":
                setAreaToDraw();
                break;
            case "grain-button":
                drawGrainsTmp();
                break;
            case "wall-button":
                drawWallsTmp();
                break;
            case "delete-button":
                drawDeleteTmp();
                break;
            default:
                return;
        }
    }
}

/**
 * Erzeugt einen neuen Territorium-Inhalt und füllt diesen mit leeren Zellen.
 * 
 * @returns {any[]} 2D-Matrix mit CellContents.
 */
export function createNewTerritoryContent() {
    let territoryContentNew = new Array(rows);
    for (let r = 0; r < rows; r++) {
        territoryContentNew[r] = new Array(cols);
    }
    // fill Territory matrix
    for (let r = 0; r < rows; r++) {
        for (let c = 0; c < cols; c++) {
            if (r < territoryContent.length && c < territoryContent[r].length) {
                territoryContentNew[r][c] = territoryContent[r][c];
            } else {
                territoryContentNew[r][c] = new CellContent();
            }
        }
    }
    
    territoryContent = territoryContentNew;
    
    return territoryContentNew;
}

/**
 * Blendet für die Zelle der aktuellen Pointer-Koordinaten den Info-Tooltip ein.
 */
function showCanvasInfo() {
    let actualCellContent = territoryContent[pointerY][pointerX];
    showTerritoryTooltip(actualCellContent);
}

/**
 * Setzt bei den ausgewählten Zellen des Territoriums das Korn-Attribut auf wahr und zeichnet anschließend den
 * Inhalt des Territoriums neu.
 * 
 * @param numberOfGrains, Anzahl der Körner, die hinzugefügt werden sollen.
 */
function updateTerritoryGrain(numberOfGrains) {
    let territoryContentNew = createNewTerritoryContent();

    for (let r = pointerStartY; r <= pointerEndY; r++) {
        for (let c = pointerStartX; c <= pointerEndX; c++) {
            if (r >= rows || c >= cols) {
                continue;
            }
            
            if (territoryContentNew[r][c].hasWall()) {
                territoryContentNew[r][c].setWall(false);
            }

            territoryContentNew[r][c].setGrain(true);
            territoryContentNew[r][c].setGrainAmount(numberOfGrains);
        }
    }

    territoryContent = territoryContentNew;
    drawAll();
}

/**
 * Setzt bei den ausgewählten Zellen des Territoriums das wall-Attribut auf wahr und zeichnet anschließend den
 * Inhalt des Territoriums neu.
 */
function updateTerritoryWall() {
    let territoryContentNew = createNewTerritoryContent();
   
    for (let r = pointerStartY; r <= pointerEndY; r++) {
        for (let c = pointerStartX; c <= pointerEndX; c++) {
            if (r >= rows || c >= cols) {
                continue;
            }
            
            if (territoryContentNew[r][c].hasGrain()) {
                territoryContentNew[r][c].setGrainAmount(0);
                territoryContentNew[r][c].setGrain(false);
            }
            
            if (territoryContentNew[r][c].getNumberOfHamster() > 0) {
                continue;
            }

            territoryContentNew[r][c].setWall(true);
        }
    }
    
    territoryContent = territoryContentNew;
    drawAll();
}

/**
 * Setzt bei den ausgewählten Zellen des Territoriums alle Attribute (außer Hamster) auf default und zeichnet
 * anschließend den Inhalt des Territoriums neu.
 */
function updateTerritoryDelete() {
    let territoryContentNew = createNewTerritoryContent();

    for (let r = pointerStartY; r <= pointerEndY; r++) {
        for (let c = pointerStartX; c <= pointerEndX; c++) {
            if (r >= rows || c >= cols) {
                continue;
            }
            
            territoryContentNew[r][c].setWall(false);
            territoryContentNew[r][c].setGrain(false);
            territoryContentNew[r][c].setGrainAmount(0);
        }
    }

    territoryContent = territoryContentNew;
    drawAll();
}

/**
 * Setzt den Bereich zum Zeichnen fest und sorgt dafür, dass alles neu gezeichnet wird.
 */
function setAreaToDraw() {
    if (offsetEndX < offsetStartX) {
        pointerStartX = pointerX;
    } else {
        pointerEndX = pointerX;
    }

    if (offsetEndY < offsetStartY) {
        pointerStartY = pointerY;
    } else {
        pointerEndY = pointerY;
    }

    drawHamsters();
}

/**
 * Zeichnet den Hamster während der Drag-und-Drop-Aktion im Territorium.
 */
function drawHamsterTmp() {
    actorImage = hamster.getActorImage();
    territory.drawImage(actorImage, offsetX - (actorImage.width / 2), offsetY - (actorImage.height /2));
    hamsters.forEach(function (hamster) {
        if (!hamster.isInitialized() || hamster.getName() === "hamster") {
            return;
        }
        
        drawHamsterInTerritory(hamster);
    });
}

function drawHamsterInTerritory(hamster) {
    hamsterX = hamster.getColumn() * cellWidth + cellWidth / 2;
    hamsterY = hamster.getRow() * cellHeight + cellHeight / 2;
    actorImage = hamster.getActorImage();
    territory.drawImage(actorImage, hamsterX - (actorImage.width / 2), hamsterY - (actorImage.height / 2));
    territoryContent[hamster.getRow()][hamster.getColumn()].addHamster(hamster);
}

/**
 * Zeichnet im aktuellen Drag-und-Drop-Bereich des Territoriums in jede Zelle ein Korn.
 */
function drawGrainsTmp() {
    setAreaToDraw();
    for (let r = pointerStartY; r <= pointerEndY; r++) {
        for (let c = pointerStartX; c <= pointerEndX; c++) {
            if (r >= rows || c >= cols) {
                continue;
            }
            
            calculateCurrentPositionFromCoords(r, c);
            territory.drawImage(grainImage, currentX - (grainImage.width / 2), currentY - (grainImage.height / 2), 40, 40);
            
            if (territoryContent[r][c].getNumberOfHamster() > 0) {
                drawHamsters();
            }
        }
    }
}

/**
 * Zeichnet im aktuellen Drag-und-Drop-Bereich des Territoriums in jede Zelle, die keinen Hamster enthält eine Mauer.
 */
function drawWallsTmp() {
    setAreaToDraw();
    
    for (let r = pointerStartY; r <= pointerEndY; r++) {
        for (let c = pointerStartX; c <= pointerEndX; c++) {
            if (r >= rows || c >= cols) {
                continue;
            }
            
            calculateCurrentPositionFromCoords(r, c);
            if (territoryContent[r][c].getNumberOfHamster() > 0) {
                continue;
            }
            
            territory.drawImage(wallImage, currentX - (wallImage.width / 2), currentY - (wallImage.height / 2));
        }
    }
}

/**
 * Zeichnet im aktuellen Drag-und-Drop-Bereich des Territoriums in jede Zelle ein Löschen-Symbol.
 */
function drawDeleteTmp() {
    setAreaToDraw();

    for (let r = pointerStartY; r <= pointerEndY; r++) {
        for (let c = pointerStartX; c <= pointerEndX; c++) {
            if (r >= rows || c >= cols) {
                continue;
            }
            
            calculateCurrentPositionFromCoords(r, c);
            if (territoryContent[r][c].getNumberOfHamster() > 0 && !territoryContent[r][c].hasGrain()) {
                continue;
            }

            territory.drawImage(deleteImage, currentX - (deleteImage.width / 2), currentY - (deleteImage.height / 2));
        }
    }
}

/**
 * Berechnet die aktuelle Position innerhalb des Territoriums.
 * 
 * @param x -Koordinate.
 * @param y -Koordinate.
 */
function calculateCurrentPositionFromCoords(x, y) {
    currentX = y * cellWidth + cellWidth/2;
    currentY = x * cellHeight + cellHeight/2;
}


/**
 * Zeichnet die Basis des Territoriums, teilt es grafisch in eine 2D-Matrix ein und füllt es mit Farbe.
 */
function draw() {
    territory.clearRect(0, 0, canvas.width, canvas.height);
    territory.fillStyle = "rgb(166, 225, 163)";
    territory.fillRect(0, 0, canvas.width, canvas.height);
    for (let i = 0; i < canvas.width; i += cellWidth) {
        for (let j = 0; j < canvas.height; j += cellHeight) {
            territory.beginPath();
            territory.strokeStyle = "rgb(139, 69, 19)";
            territory.strokeRect(i, j, cellWidth, cellHeight);
            territory.closePath();
        }
    }
}

/**
 * Ändert die Größe des Territoriums. Das Territorium und seine Elemente wird anschließend neu gezeichnet.
 */
export function resizeTerritory(event) {
    event.preventDefault();

    let newRows = parseInt(rowInput.value);
    let newCols = parseInt(colInput.value);

    rows = newRows;
    cols = newCols;
    
   
    
    // Setzt den Default-Hamster auf 0 0, falls die alte Position nicht mehr möglich ist.
    if (hamster.getRow() >= rows || hamster.getColumn() >= cols) {
        hamster.setRow(0);
        hamster.setColumn(0);
        
        if (territoryContent[hamster.getRow()][hamster.getColumn()].hasWall()) {
            territoryContent[hamster.getRow()][hamster.getColumn()].setWall(false);
        }
    }
    
    closeChangeSizeDialog();
    calculateCanvasSize();
    calculateGridSize();
    createNewTerritoryContent();
    saveTemporaryTerritory();
    drawAll();
}

/**
 * Berechnet die Größe, die das Canvas benötigt.
 */
export function calculateCanvasSize() {
    canvas.width = cols * cellWidth;
    canvas.height = rows * cellHeight;
}

/**
 * Teilt das Territorium in eine 2D-Matrix auf.
 */
function createCellContent() {
    territoryContent = new Array(rows);
    for (let r = 0; r < rows; r++) {
        territoryContent[r] = new Array(cols);
    }
}

/**
 * Zeichnet alle Hamster aus dem Hamster-Array in die entsprechende Zelle innerhalb des Territoriums.
 */
export function drawHamsters() {
    hamsters.forEach(function (hamster) {
        if (!hamster.isInitialized() || territoryContent[hamster.getRow()][hamster.getColumn()].hasWall()) {
            return;
        }
        
        drawHamsterInTerritory(hamster);
    });
}

/**
 * Initialisiert das Territorium mit Zellen.
 */
function initTerritory() {
    createCellContent();
    // fill Territory matrix
    for (let r = 0; r < rows; r++) {
        for (let c = 0; c < cols; c++) {
            territoryContent[r][c] = new CellContent();
        }
    }
}

/**
 * Zeichnet für jede Zelle innerhalb des Territoriums den Inhalt in das Canvas.
 */
function drawTerritoryContent() {
    for (let r = 0; r < rows; r++) {
        for (let c = 0; c < cols; c++) {
            let x = cellWidth * c + cellWidth/2;
            let y = cellHeight * r + cellHeight/2;
            if (!territoryContent[r][c].hasWall() && !territoryContent[r][c].hasGrain()) {
                territory.fillRect(c*cellWidth+1, r*cellHeight+1, cellWidth-2, cellHeight-2);
            } else if (territoryContent[r][c].hasWall()) {
                territory.drawImage(wallImage, x - (wallImage.width / 2), y - (wallImage.height / 2));
            } else {
                territory.fillRect(c*cellWidth+1, r*cellHeight+1, cellWidth-2, cellHeight-2);
                drawGrains(r, c);
            }
        }
    }
}

/**
 * Zeichnet die Anzahl der Körner in die entsprechende Zelle des Territoriums.
 * 
 * @param row, betreffende Reihe.
 * @param column, betreffende Spalte.
 */
function drawGrains(row, column) {
    let numberOfGrains = territoryContent[row][column].getNumberOfGrains();
    for (let x = 2; x <= cellWidth - (cellWidth/5 + 2); x += cellWidth/5 + 2) {
        for (let y = 2, maxCorns = 4; y <= cellHeight - (cellHeight/5 + 2) && numberOfGrains > 0 && maxCorns > 0; y += cellHeight/5 + 2, numberOfGrains--, maxCorns--) {
            territory.drawImage(grainImage, column*cellWidth + x, row*cellHeight + y, cellWidth/5, cellHeight/5);
        }
    }
}

/**
 * Zeichnet das gesamte Canvas mit allen Inhalten neu.
 * 
 * Zeichnet das Basic-Territorium, die Zelleninhalte sowie alle Hamster aus dem Hamster-Array.
 */
export function drawAll() {
    draw();
    drawTerritoryContent();
    // Timeout nötig, da Hamster sonst manchmal nicht richtig gezeichnet wird.
    window.setTimeout(drawHamsters, 30);
}

/**
 * Berechnet die Größe, die das Grid benötigt.
 */
export function calculateGridSize() {
    let contentWrapper = document.getElementById('content-wrapper');
    let header = document.getElementById('header');
    let headerHeight = header.offsetHeight;
    let newHeight = getScreenHeight()-headerHeight; //Magic numbers für genaue Berechnung leider nötig

    contentWrapper.style.maxHeight = newHeight.toString() + "px";
}

/**
 * Liefert die aktuelle Bildschirmbreite des Clients.
 *
 * @returns {number} Bildschirmbreite des Clients.
 */
export function getScreenWidth() {
    return document.body.clientWidth;
}

/**
 * Liefert die aktuelle Bildschirmhöhe des Clients.
 *
 * @returns {number} Bildschirmhöhe des Clients.
 */
export function getScreenHeight() {
    return document.body.clientHeight;
}

/**
 * Repräsentiert eine Zelle innerhalb des Territoriums.
 */
export class CellContent {

    constructor(obj) {
        if (obj === undefined) {
            this.hamsters = [];
            this.wall = false;
            this.grain = false;
            this.numberOfGrains = 0;
        } else {
            Object.assign(this, obj);
        }
    }
    
    getHamster() {
        return this.hamsters;
    }

    getNumberOfHamster() {
        return this.hamsters.length;
    }
    
    hasWall() {
        return this.wall;
    }
    
    hasGrain() {
        return this.grain;
    }
    
    getNumberOfGrains() {
        return this.numberOfGrains;
    }
    
    addHamster(hamster) {
        for (let i = 0; i < this.hamsters.length; i++) {
            if (this.hamsters[i] === hamster) {
                return;
            }
        }

        this.hamsters.push(hamster);
    }

    removeHamster(hamster) {
        const index = this.hamsters.indexOf(hamster);
        if (index > -1) {
            this.hamsters.splice(index, 1);
        }
    }


    setWall(wall) {
        this.wall = wall;
    }

    setGrain(corn) {
        this.grain = corn;
    }

    setGrainAmount(numberOfGrains) {
        if (numberOfGrains >= 0) {
            this.numberOfGrains = numberOfGrains;
            if (numberOfGrains > 0) {
                this.grain = true;
            }
        }
    }

    incrementNumberOfGrains() {
        this.numberOfGrains++;
    }
    
    decrementNumberOfGrains() {
        if (this.numberOfGrains > 0) {
            this.numberOfGrains--;
            if (this.numberOfGrains === 0) {
                this.grain = false;
            }
        }
    }
    
    isEmpty() {
        return this.hamsters === false && this.wall === false && this.grain === false;
    }

}