type Direction = "R" | "L" | "U" | "D";

type Instruction = {
    direction: Direction;
    steps: number;
    color: number;
}

async function readInput(filename: string): Promise<Instruction[]> {
    const input = await Deno.readTextFile(filename);
    const lines = input.split("\n").map(x => x.trim()).filter(x => x.length > 0);
    return lines.map(line => {
        const m = /^([RDLU])\s+(\d+)\s+\(#([0-9a-f]+)\)$/.exec(line);
        if (!m) {
            throw new Error(`unknown line ${line}`);
        }
        return {
            direction: m[1] as Direction,
            steps: parseInt(m[2]),
            color: parseInt(m[3], 16),
        }
    });
}

const input = await readInput("input.txt");

function calcWidthAndHeight(insts: Instruction[]){
    let maxX = 0, maxY = 0;
    let minX = 0, minY = 0;
    insts.reduce<[number,number]>(([x,y]: [number, number], b: Instruction) => {
        maxX = Math.max(maxX, x);
        maxY = Math.max(maxY, y);
        minX = Math.min(minX, x);
        minY = Math.min(minY, y);

        if (b.direction === "R"){
            return [x + b.steps, y];
        }
        if (b.direction === "L"){
            return [x - b.steps, y];
        }
        if (b.direction === "U"){
            return [x, y - b.steps];
        }
        if (b.direction === "D"){
            return [x, y + b.steps];
        }
        throw new Error(`unknown direction ${b.direction}`);
    }, [0,0] as [number, number]);
    return {
        size: [maxX - minX + 1, maxY - minY + 1],
        initPos: [-minX, -minY]
    };
}
const {size:[width, height],
initPos: [initX, initY]} = calcWidthAndHeight(input);

console.log((`x: ${width}, y: ${height}`));

function drawMap(instructions: Instruction[], initX: number, initY: number, width: number, height:number){
    const map = new Array(height).fill(0).map(()=>new Array(width).fill(".")) as string[][];
    let [x, y] = [initX, initY];
    instructions.forEach(({direction, steps, color}) => {
        for (let i = 0; i < steps; i++) {
            if (direction === "R"){
                map[y][x] = "#"//rgb24("#", color);
                x++;
            }
            if (direction === "L"){
                map[y][x] = "#"//rgb24("#", color);
                x--;
            }
            if (direction === "U"){
                map[y][x] = "#"//rgb24("#", color);
                y--;
            }
            if (direction === "D"){
                map[y][x] = "#"//rgb24("#", color);
                y++;
            }
        }
    });

    // fill inner
    for (let i = 1; i < height - 1; i++) {
        let isInner = false;
        let upDetected = false;
        let downDetected = false;
        let j = 0;
        while (j < width - 1) {
            if (map[i][j] === "#"){
                if (map[i - 1][j] === "#"){
                    upDetected = !upDetected;
                }
                if (map[i + 1][j] === "#"){
                    downDetected = !downDetected;
                }
                if (upDetected && downDetected){
                    isInner = true;
                }
                if (!upDetected && !downDetected){
                    isInner = false;
                }
            }
            if (isInner && map[i][j] === "."){
                map[i][j] = "@";
            }
            j++;
        }
    }
    // console.log(map.map(x => x.join("")).join("\n"));
    return map.map(x => x.join("")).join("\n");
}

const map = drawMap(input, initX, initY, width, height);
await Deno.writeTextFile("output.txt", map);

console.log(map.split("").filter(x => x === "#" || x === "@").length);


