// @ts-nocheck
import { layout } from '../util/layout';

const processCorner = (game: any, color: string, cornerIndex: number, placedCorner: any): number => {
  /* If this corner is allocated and isn't assigned to the walking color, skip it */
  if (placedCorner.color && placedCorner.color !== color) {
    return 0;
  }
  /* If this corner is already being walked, skip it */
  if (placedCorner.walking) {
    return 0;
  }

  placedCorner.walking = true;
  /* Calculate the longest road branching from both corners */
  let longest = 0;
  layout.corners[cornerIndex].roads.forEach((roadIndex: number) => {
    const placedRoad = game.placements.roads[roadIndex];
    if (!placedRoad) {
      return;
    }
    if (placedRoad.walking) {
      return;
    }
    const tmp = processRoad(game, color, roadIndex, placedRoad);
    longest = Math.max(tmp, longest);
    /*if (tmp > longest) {
      longest = tmp;
      placedCorner.longestRoad = roadIndex;
      placedCorner.longest
    }
    longest = Math.max(
      */
  });

  return longest;
};

const buildCornerGraph = (game: any, color: string, cornerIndex: number, placedCorner: any, set: any) => {
  /* If this corner is allocated and isn't assigned to the walking color, skip it */
  if (placedCorner.color && placedCorner.color !== color) {
    return;
  }
  /* If this corner is already being walked, skip it */
  if (placedCorner.walking) {
    return;
  }

  placedCorner.walking = true;
  /* Calculate the longest road branching from both corners */
  layout.corners[cornerIndex].roads.forEach((roadIndex: number) => {
    const placedRoad = game.placements.roads[roadIndex];
    if (!placedRoad) return;
    buildRoadGraph(game, color, roadIndex, placedRoad, set);
  });
};

const processRoad = (game: any, color: string, roadIndex: number, placedRoad: any): number => {
  /* If this road isn't assigned to the walking color, skip it */
  if (placedRoad.color !== color) {
    return 0;
  }

  /* If this road is already being walked, skip it */
  if (placedRoad.walking) {
    return 0;
  }

  placedRoad.walking = true;
  /* Calculate the longest road branching from both corners */
  let roadLength = 1;
  layout.roads[roadIndex].corners.forEach((cornerIndex) => {
    const placedCorner = game.placements.corners[cornerIndex];
    if (!placedCorner) return;
    if (placedCorner.walking) {
      return;
    }
    roadLength += processCorner(game, color, cornerIndex, placedCorner);
  });

  return roadLength;
};

const buildRoadGraph = (game: any, color: string, roadIndex: number, placedRoad: any, set: any) => {
  /* If this road isn't assigned to the walking color, skip it */
  if (placedRoad.color !== color) {
    return;
  }
  /* If this road is already being walked, skip it */
  if (placedRoad.walking) {
    return;
  }

  placedRoad.walking = true;
  set.push(roadIndex);
  /* Calculate the longest road branching from both corners */
  layout.roads[roadIndex].corners.forEach((cornerIndex) => {
    const placedCorner = game.placements.corners[cornerIndex];
    if (!placedCorner) return;
    buildCornerGraph(game, color, cornerIndex, placedCorner, set);
  });
};

const clearRoadWalking = (game: any) => {
  /* Clear out walk markers on roads */
  layout.roads.forEach((item, itemIndex) => {
    if (game.placements && game.placements.roads && game.placements.roads[itemIndex]) {
      delete game.placements.roads[itemIndex].walking;
    }
  });

  /* Clear out walk markers on corners */
  layout.corners.forEach((item, itemIndex) => {
    if (game.placements && game.placements.corners && game.placements.corners[itemIndex]) {
      delete game.placements.corners[itemIndex].walking;
    }
  });
}

const calculateRoadLengths = (game: any) => {
  const color = game.color;
  clearRoadWalking(game);

  /* Build a set of connected road graphs. Once all graphs are 
   * constructed, walk through each graph, starting from each
   * location in the graph. If the length ever equals the
   * number of items in the graph, short circuit--longest path.
   * Otherwise, check all paths from each segment. This is
   * needed to catch loops where starting from an outside end
   * point may result in not counting the length of the loop
   */
  let graphs = [];
  layout.roads.forEach((_, roadIndex) => {
    const placedRoad = game.placements.roads[roadIndex];
    if (!placedRoad) return;
    if (placedRoad.color === color) {
      let set = [];
      buildRoadGraph(game, color, roadIndex, placedRoad, set);
      if (set.length) {
        graphs.push({ color, set });
      }
    }
  });

  let final = {
    segments: 0,
    index: -1,
  };

  clearRoadWalking(game);
  graphs.forEach((graph) => {
    graph.longestRoad = 0;
    graph.set.forEach((roadIndex) => {
      const placedRoad = game.placements.roads[roadIndex];
      clearRoadWalking(game);
      const length = processRoad(game, color, roadIndex, placedRoad);
      if (length >= graph.longestRoad) {
        graph.longestStartSegment = roadIndex;
        graph.longestRoad = length;
        if (length > final.segments) {
          final.segments = length;
          final.index = roadIndex;
        }
      }
    });
  });

  game.placements.roads.forEach((road: any) => {
    if (road) delete road.walking;
  });

  return final;
};

export default calculateRoadLengths;