const input = await Deno.readTextFile("input.txt");
const lines = input.split("\n").map(x => x.trim()).filter(x => x.length > 0).map(x => x.split(""));

const width = lines[0].length;
const height = lines.length;

function slideRock(maps: string[][], dir: "north" | "south" | "east" | "west") {
    switch (dir) {
        case "north":
            for (let i = 0; i < width; i++) {
                let place = 0;
                for (let j = 0; j < height; j++) {
                    const ch = maps[j][i];
                    if (ch === "O") {
                        //swap
                        const tmp = maps[place][i];
                        maps[place][i] = ch;
                        maps[j][i] = tmp;
                        place++;
                    }
                    else if (ch === ".") {
                        // do nothing
                    }
                    else if (ch === "#") {
                        place = j + 1;
                    }
                    else {
                        throw new Error(`unknown char ${ch}`);
                    }
                }
            }
            break;
        case "east":
            for (let i = 0; i < height; i++) {
                let place = 0;
                for (let j = 0; j < width; j++) {
                    const ch = maps[i][j];
                    if (ch === "O") {
                        //swap
                        const tmp = maps[i][place];
                        maps[i][place] = ch;
                        maps[i][j] = tmp;
                        place++;
                    }
                    else if (ch === ".") {
                        // do nothing
                    }
                    else if (ch === "#") {
                        place = j + 1;
                    }
                    else {
                        throw new Error(`unknown char ${ch}`);
                    }
                }
            }
            break;
        case "south":
            for (let i = 0; i < width; i++) {
                let place = height - 1;
                for (let j = height - 1; j >= 0; j--) {
                    const ch = maps[j][i];
                    if (ch === "O") {
                        //swap
                        const tmp = maps[place][i];
                        maps[place][i] = ch;
                        maps[j][i] = tmp;
                        place--;
                    }
                    else if (ch === ".") {
                        // do nothing
                    }
                    else if (ch === "#") {
                        place = j - 1;
                    }
                    else {
                        throw new Error(`unknown char ${ch}`);
                    }
                }
            }
            break;
        case "west":
            for (let i = 0; i < height; i++) {
                let place = width - 1;
                for (let j = width - 1; j >= 0; j--) {
                    const ch = maps[i][j];
                    if (ch === "O") {
                        //swap
                        const tmp = maps[i][place];
                        maps[i][place] = ch;
                        maps[i][j] = tmp;
                        place--;
                    }
                    else if (ch === ".") {
                        // do nothing
                    }
                    else if (ch === "#") {
                        place = j - 1;
                    }
                    else {
                        throw new Error(`unknown char ${ch}`);
                    }
                }
            }
            break;
    }
}

function cycle(maps: string[][]){
    slideRock(maps, "north");
    slideRock(maps, "east");
    slideRock(maps, "south");
    slideRock(maps, "west");
}

const towardsMap = lines.map(x => [...x]);
let i = 0;
for (i = 0; i < 1000000000; i++) {
    cycle(lines);
    cycle(towardsMap);
    cycle(towardsMap);
    if (towardsMap.every((x,i) => x.join("") === lines[i].join(""))){
        break;
    }
}
const start = i + 1;
console.log("i", i);
for (i = 0; i < 1000000000; i++) {
    cycle(lines);
    cycle(towardsMap);
    cycle(towardsMap);
    // await Deno.writeTextFile(`exampleCycle/${step}.txt`, lines.map(x => x.join("")).join("\n"));
    if (towardsMap.every((x,i) => x.join("") === lines[i].join(""))){
        break;
    }
}

const step = i + 1;
console.log("step", step);

console.log(`index ${(1000000000 - start) % step}`);

for (i = 0 ; i < (1000000000 - start) % step; i++) {
    cycle(lines);
}

const answer = lines.map((x, i) => {
    // count O
    const count = x.map(y => y === "O" ? 1 : 0 as number).reduce((acc, x) => acc + x, 0);
    return (lines.length - i) * count;
}).reduce((a, b) => a + b, 0);

console.log(answer);