const API_URL = window.__env__ !== undefined && window.__env__["API_URL"] !== "$API_URL" ? window.__env__["API_URL"] : `http://localhost:3006`

const numberToColor = (nmbr) => {
    switch(nmbr) {
        case 0: return 'red'
        case 1: return 'green'
        case 2: return 'blue'
        case 3: return 'orange'
        case 4: return 'black'
        case 5: return 'purple'
        case 6: return 'yellow'
        case 7: return 'indigo'
        case 8: return 'violet'
        case 9: return 'teal'
        case 10: return 'brown'
        case 11: return 'gray'
        case 12: return 'bordeaux'
        default: return null
    }
}

let currentlyHoveredTarget = null
let currentlyHoveredCoords = {x: 0, y: 0}
let cookie = ""

function drag() {
    window.addEventListener("dragover", (event) => {
        if(event.target.attributes["class"].value === "col") {
            currentlyHoveredTarget = event.target
            
            const root = document.getElementById("puzzle");
             
            const found = [...root.childNodes.entries()].flatMap(([y, row]) => {
                const found = [...row.childNodes.entries()].flatMap(([x, col]) => col.isEqualNode(event.target) ? [x] : [])
                if(found.length > 0) {
                    return [[found[0], y]]
                } else {
                    return []
                }
            })

            if(found.length > 0) {
                currentlyHoveredCoords = {x: found[0][0], y: found[0][1]}
            }
        }
    })
}

function redraw(json, coveredJson) {
    const root = document.getElementById("puzzle");

    [...root.childNodes.entries()].forEach(([y, row]) => [...row.childNodes.entries()].forEach(([x, col]) => {
        const jsonColor = json[y][x]
        const coveredColor = coveredJson[y][x]

        if(jsonColor !== null) {
            col.setAttribute("style", `background-color: ${numberToColor(jsonColor)}; cursor: pointer;`)
        } else if(coveredColor !== null) {
            col.setAttribute("style", `background-color: ${numberToColor(coveredColor)};`)
        } else {
            col.removeAttribute("style")
        }
    }))
}

async function fetchFlow() {
    const response = await fetch(API_URL, {credentials: "include"})
    if(!response.ok) {
        return
    }
    startTimer()

    /**Puzzle: {grid: Array<Array<number | null>>, line_count: number, width: number, height: number} */
    /**json: {level: number, total: number, puzzle: Puzzle} */
    const json = await response.json()
    let coveredGrid = json.grid.map(row => row.map(col => col))

    drawFlow(json, coveredGrid)
}

function drawFlow(json, coveredGrid) {

    const main = document.getElementById("main")
    main.setAttribute("style", `width: ${100 * json.width}px;`)

    const submitButton = document.getElementById("submit-solution")
    submitButton.addEventListener("click", async (event) => {
        const response = await fetch(API_URL, {
            method: "POST",
            body: JSON.stringify({...json, grid: coveredGrid}),
            credentials: "include"
        })
        stopTimer()

        const answerJson = await response.json()
        const headerDiv = document.getElementById("header")
        const headers = [...headerDiv.getElementsByTagName("h1")]
        headers.forEach(header => header.remove())
        const answerHeader = document.createElement("h1")
        answerHeader.innerText = answerJson.message
        if(answerJson.time !== undefined) {
            answerHeader.innerText += `, time: ${answerJson.time}s`
        }
        headerDiv.append(answerHeader)
    })

    const grid = json.grid

    const puzzleDiv = document.getElementById("puzzle")
    puzzleDiv.innerHTML = ""

    grid.forEach((row, y) => {
        const rowDiv = document.createElement("div")

        rowDiv.setAttribute("class", "row")

        row.forEach((col, x) => {
            const colDiv = document.createElement("div")

            colDiv.setAttribute("class", "col")
            colDiv.setAttribute("draggable", true)
            colDiv.setAttribute("x", x)
            colDiv.setAttribute("y", y)

            if(col !== null) {
                if(grid[y][x] !== null) {
                    colDiv.setAttribute("style", `background-color: ${numberToColor(col)}; cursor: pointer;`)
                }
                colDiv.addEventListener("drag", (event) => {
                    if(currentlyHoveredTarget === null) {
                        return
                    }
                    if(currentlyHoveredCoords.x === x && currentlyHoveredCoords.y === y) {
                        coveredGrid = coveredGrid.map((r, y) => r.map((c, x) => {
                            const jsonGridVal = grid[y][x]
                            return c === col ? jsonGridVal : c
                        }))
                    }
    
                    const square = grid[currentlyHoveredCoords.y][currentlyHoveredCoords.x]


                    if(
                        grid[currentlyHoveredCoords.y][currentlyHoveredCoords.x] === null && coveredGrid[currentlyHoveredCoords.y][currentlyHoveredCoords.x] === null &&
                        ((currentlyHoveredCoords.y-1 >= 0 && (grid[currentlyHoveredCoords.y-1][currentlyHoveredCoords.x] === col || coveredGrid[currentlyHoveredCoords.y-1][currentlyHoveredCoords.x] === col)) ||
                        (currentlyHoveredCoords.y+1 < grid.length && (grid[currentlyHoveredCoords.y+1][currentlyHoveredCoords.x] === col || coveredGrid[currentlyHoveredCoords.y+1][currentlyHoveredCoords.x] === col)) ||
                        (currentlyHoveredCoords.x-1 >= 0 && (grid[currentlyHoveredCoords.y][currentlyHoveredCoords.x-1] === col || coveredGrid[currentlyHoveredCoords.y][currentlyHoveredCoords.x-1] === col)) ||
                        (currentlyHoveredCoords.x+1 < grid[0].length && (grid[currentlyHoveredCoords.y][currentlyHoveredCoords.x+1] === col || coveredGrid[currentlyHoveredCoords.y][currentlyHoveredCoords.x+1] === col)))
                    ) {
                        coveredGrid[currentlyHoveredCoords.y][currentlyHoveredCoords.x] = col
                    }
    
                    redraw(grid, coveredGrid)
                    
                })
            }



            rowDiv.append(colDiv)
        })

        puzzleDiv.append(rowDiv)
    })

}

let timerInterval = null
async function startTimer() {
    const timer = document.getElementById("timer")
    let ms = 0
    timerInterval = setInterval(() => {
        ms++
        const seconds = Math.floor(ms / 100)
        const remainder = ms - (seconds * 100)
        timer.innerText = `${seconds}.${remainder}`
    }, 10)
}

function stopTimer() {
    clearInterval(timerInterval)
}