import { CharColl, Coll, Collection, Collection2D } from "util/collection";

// If blank strings/ints is not enough
export const inputMapper = (inputs: string) =>
  CharColl(inputs).map((c) => parseInt(c));

function lookBack(arr: Collection<number>, index: number) {
  const curr = arr[index];
  for (let i = index - 1; i >= 0; i--) {
    if (arr[i] >= curr) {
      return false;
    }
  }
  return true;
}

function lookForward(arr: Collection<number>, index: number) {
  const curr = arr[index];
  for (let i = index + 1; i < arr.length; i++) {
    if (arr[i] >= curr) {
      return false;
    }
  }
  return true;
}

export function solution1(inputs: Collection2D<number>): number {
  let visible = 0;

  for (let y = 1; y < inputs.length - 1; y++) {
    for (let x = 1; x < inputs[0].length - 1; x++) {
      const column = inputs.map((row) => row[x]);

      if (
        lookBack(inputs[y], x) || lookForward(inputs[y], x) ||
        lookBack(column, y) || lookForward(column, y)
      ) {
        visible++;
      }
    }
  }

  return visible + inputs.length * 2 + inputs[0].length * 2 - 4;
}

export function countBack(arr: Collection<number>, index: number): number {
  const curr = arr[index];
  let steps = 1;

  for (let i = index - 1; i >= 0; i--, steps++) {
    if (arr[i] >= curr) {
      return steps;
    }

    if (i === 0) {
      // Steps counts up by one for the last iteration aswell..
      steps--;
    }
  }
  return steps;
}

export function countForward(arr: Collection<number>, index: number) {
  const curr = arr[index];
  let steps = 1;

  for (let i = index + 1; i < arr.length; i++, steps++) {
    if (arr[i] >= curr) {
      return steps;
    }

    if (i === arr.length - 1) {
      // Steps counts up by one for the last iteration aswell..
      steps--;
    }
  }
  return steps;
}

export function solution2(inputs: Collection2D<number>): number {
  let highestView = 0;

  for (let y = 1; y < inputs.length - 1; y++) {
    for (let x = 1; x < inputs[0].length - 1; x++) {
      const column = inputs.map((row) => row[x]);

      const viewScore = countBack(inputs[y], x) * countForward(inputs[y], x) *
        countBack(column, y) * countForward(column, y);

      if (viewScore > highestView) {
        highestView = viewScore;
      }
    }
  }

  return highestView;
}
