const fs = require('fs/promises');

const sum = (arr) => arr.reduce((total, num) => total+num, 0);
const arrayOfLength = n => Array.from(Array(n).keys()).map(() => {});
                //minus
const shapes = [
  [[2,0],[3,0],[4,0],[5,0]],
  [[3,0],[2,1],[3,1],[4,1],[3,2]],
  [[2,0],[3,0],[4,0],[4,1],[4,2]],
  [[2,0],[2,1],[2,2],[2,3]],
  [[2,0],[3,0],[2,1],[3,1]]
];

const keypress = async () => {
  process.stdin.setRawMode(true)
  return new Promise(resolve => process.stdin.once('data', data => {
    const byteArray = [...data]
    if (byteArray.length > 0 && byteArray[0] === 3) {
      console.log('^C')
      process.exit(1)
    }
    process.stdin.setRawMode(false)
    resolve()
  }))
}

let shapeCount = 0;

const getNextShape = (height) => {
  const shape = shapes[shapeCount % 5];
  shapeCount++;
  return shape.map(([x, y]) => [x, y + height]);
}

const getTopMost = (rocks) => Math.max(0, ...rocks);


const coords = ([x, y]) => `${x}-${y}`;

const main = async () => {
  const input = (await fs.readFile("./input.txt", 'utf8')).slice(0, -1);
  const fallenRocks = {};

  let tallestPoint = 0;
  const isColiding = (shape) => {
    if(shape.some(([x]) => x < 0 || x >= 7)) {
      return true;
    }
    if(shape.some(([_, y]) => y <= 0)) {
      return true;
    }
    const rockBottom = Math.min(...shape.map(([_, y]) => y))
    if(rockBottom <= tallestPoint && shape.some(x => fallenRocks[coords(x)])) {
      return true;
    }
    return false;
  };


  const shapeShift = (shape, direction) => {
    let nextPos;
    if(direction === "<") {
      nextPos = shape.map(([x, y]) => [x - 1, y]);
    }
    if(direction === ">") {
      nextPos = shape.map(([x, y]) => [x + 1, y]);
    }
    if(direction === "V") {
      nextPos = shape.map(([x, y]) => [x, y - 1]);
    }

    return nextPos && !isColiding(nextPos) ? nextPos : shape;
  };
  let jetTracker = 0;

  let lastCount = 0;
  let lastHeight = 0;
  let firstCountDiff = 0;
  let firstHeightDiff = 0;
  let lastCountDiff = 0;
  let lastHeightDiff = 0;

  const target = 1000000000000;
  const letFall = () => {
    if(jetTracker === 0) {
      lastCountDiff = shapeCount - lastCount;
      lastHeightDiff = tallestPoint - lastHeight;
      if(!firstCountDiff) {
        firstCountDiff = lastCountDiff;
      }
      if(!firstHeightDiff) {
        firstHeightDiff = lastHeightDiff;
      }

      lastCount = shapeCount;
      lastHeight = tallestPoint;
    }
    let shape = getNextShape(tallestPoint + 4)

    while(true) {
      const jetMoved = shapeShift(shape, input[jetTracker]);
      jetTracker = (jetTracker + 1) % input.length;
      shape = shapeShift(jetMoved, "V")
      if(shape === jetMoved) {
        const newTallest = getTopMost(jetMoved.map(([_, y]) => y));
        tallestPoint = Math.max(newTallest, tallestPoint);
        for(const unit of jetMoved) {
          fallenRocks[coords(unit)] = unit[1];
        }
        break;
      }
    }
  };
  while(shapeCount < 50000) {
    letFall();
  }
  let answer = firstHeightDiff + Math.floor((target - firstCountDiff) / lastCountDiff) * lastHeightDiff;
  const neededDiffForRemainder =  (target - firstCountDiff) % lastCountDiff;

  let neededRemainder;
  while(shapeCount < 200000) {
    letFall();
  if((shapeCount - firstCountDiff) % lastCountDiff === neededDiffForRemainder) {
      console.log("Fount it!");
      neededRemainder = tallestPoint - lastHeight;
    }
  }
  answer += neededRemainder;
  console.log("Answer: ", answer);



}

main();