import equal from "fast-deep-equal";
import { isRuleEnabled } from "../../util/validLocations";
import { addChatMessage, getName, sendUpdateToPlayers, shuffle } from "./helpers";

export const getVictoryPointRule = (game: any): number => {
  const minVP = 10;
  if (!isRuleEnabled(game, "victory-points") || !("points" in game.rules["victory-points"])) {
    return minVP;
  }
  return game.rules["victory-points"].points;
};

export const supportedRules: Record<string, (game: any, session: any, rule: any, rules: any) => string | void | undefined> = {
  "victory-points": (game: any, session: any, rule: any, rules: any) => {
    if (!("points" in rules[rule])) {
      return `No points specified for victory-points`;
    }
    if (!rules[rule].enabled) {
      addChatMessage(game, null, `${getName(session)} has disabled the Victory Point ` + `house rule.`);
    } else {
      addChatMessage(game, null, `${getName(session)} set the minimum Victory Points to ` + `${rules[rule].points}`);
    }
    return undefined;
  },
  "roll-double-roll-again": (game: any, session: any, rule: any, rules: any) => {
    addChatMessage(
      game,
      null,
      `${getName(session)} has ${rules[rule].enabled ? "en" : "dis"}abled the Roll Double, Roll Again house rule.`
    );
    return undefined;
  },
  volcano: (game: any, session: any, rule: any, rules: any) => {
    if (!rules[rule].enabled) {
      addChatMessage(game, null, `${getName(session)} has disabled the Volcano ` + `house rule.`);
    } else {
      if (!(rule in game.rules) || !game.rules[rule].enabled) {
        addChatMessage(
          game,
          null,
          `${getName(session)} enabled the Volcano ` +
            `house rule with roll set to ` +
            `${rules[rule].number} and 'Volanoes have gold' mode ` +
            `${rules[rule].gold ? "en" : "dis"}abled.`
        );
      } else {
        if (game.rules[rule].number !== rules[rule].number) {
          addChatMessage(game, null, `${getName(session)} set the Volcano roll to ` + `${rules[rule].number}`);
        }

        if (game.rules[rule].gold !== rules[rule].gold) {
          addChatMessage(
            game,
            null,
            `${getName(session)} has ` + `${rules[rule].gold ? "en" : "dis"}abled the ` + `'Volcanoes have gold' mode.`
          );
        }
      }
    }
  },

  "twelve-and-two-are-synonyms": (game: any, session: any, rule: any, rules: any) => {
    addChatMessage(
      game,
      null,
      `${getName(session)} has ${rules[rule].enabled ? "en" : "dis"}abled the Twelve and Two are Synonyms house rule.`
    );
    game.rules[rule] = rules[rule];
  },
  "most-developed": (game: any, session: any, rule: any, rules: any) => {
    addChatMessage(
      game,
      null,
      `${getName(session)} has ${rules[rule].enabled ? "en" : "dis"}abled the Most Developed house rule.`
    );
  },
  "port-of-call": (game: any, session: any, rule: any, rules: any) => {
    addChatMessage(
      game,
      null,
      `${getName(session)} has ${rules[rule].enabled ? "en" : "dis"}abled the Another Round of Port house rule.`
    );
  },
  "slowest-turn": (game: any, session: any, rule: any, rules: any) => {
    addChatMessage(
      game,
      null,
      `${getName(session)} has ${rules[rule].enabled ? "en" : "dis"}abled the Slowest Turn house rule.`
    );
  },
  "tiles-start-facing-down": (game: any, session: any, rule: any, rules: any) => {
    addChatMessage(
      game,
      null,
      `${getName(session)} has ${rules[rule].enabled ? "en" : "dis"}abled the Tiles Start Facing Down house rule.`
    );
    if (rules[rule].enabled) {
      shuffle(game, session);
    }
  },
  "robin-hood-robber": (game: any, session: any, rule: any, rules: any) => {
    addChatMessage(
      game,
      null,
      `${getName(session)} has ${rules[rule].enabled ? "en" : "dis"}abled the Robin Hood Robber house rule.`
    );
  },
};

export const setRules = (game: any, session: any, rules: any): string | undefined => {
  if (game.state !== "lobby") {
    return `You can not modify House Rules once the game has started.`;
  }

  for (let rule in rules) {
    if (equal(game.rules[rule], rules[rule])) {
      continue;
    }

    if (rule in supportedRules) {
      const handler = supportedRules[rule];
      if (handler) {
        const warning = handler(game, session, rule, rules);
        if (warning) {
          return warning;
        }
      }
      game.rules[rule] = rules[rule];
    } else {
      return `Rule ${rule} not recognized.`;
    }
  }

  sendUpdateToPlayers(game, {
    rules: game.rules,
    chat: game.chat,
  });
  return undefined;
};
