import React from "react";
import { shallow } from "enzyme";
import Lobby, { GameInfo, PlayerList } from "../components/screens/Lobby/Lobby";
import {
  COUNTRY_RACE,
  FROZEN,
  NORMAL,
  RACE,
  TIME_BANK,
} from "../domain/ruleSets";

jest.mock("iso-3166-1");
jest.mock("../domain/gameStore");
jest.mock("../hooks/useGameInfo");

import iso from "iso-3166-1";
import { useGameId } from "../domain/gameStore";
import { useGameConfig, usePlayers } from "../hooks/useGameInfo";

describe("Lobby", () => {
  it("renders while loading", () => {
    useGameId.mockReturnValue("test-game-id");
    usePlayers.mockReturnValue(null);
    const onStart = jest.fn();
    const rendered = shallow(<Lobby onStart={onStart} />);
    expect(rendered).toMatchSnapshot();
  });

  it("renders with no players", () => {
    useGameId.mockReturnValue("test-game-id");
    usePlayers.mockReturnValue([]);
    const onStart = jest.fn();
    const rendered = shallow(<Lobby onStart={onStart} />);
    expect(rendered).toMatchSnapshot();
  });

  it("renders", () => {
    useGameId.mockReturnValue("test-game-id");
    usePlayers.mockReturnValue([{ name: "foo", name: "bar" }]);
    const onStart = jest.fn();
    const rendered = shallow(<Lobby onStart={onStart} />);
    expect(rendered).toMatchSnapshot();
  });

  it("properly handles joining and starting", () => {
    useGameId.mockReturnValue("test-game-id");
    usePlayers.mockReturnValue([]);
    const onStart = jest.fn();
    const rendered = shallow(<Lobby onStart={onStart} />);
    rendered.find("JoinForm").first().prop("onJoined")();
    expect(rendered).toMatchSnapshot();
    rendered.find("StartGame").first().prop("onStart")();
    expect(onStart).toHaveBeenCalled();
  });

  describe("GameInfo", () => {
    it("renders while loading", () => {
      useGameConfig.mockReturnValue({});
      const rendered = shallow(<GameInfo />);
      expect(rendered).toMatchSnapshot();
    });

    it("renders", () => {
      useGameConfig.mockReturnValue({
        rounds: 5,
        timer: 300,
      });
      const rendered = shallow(<GameInfo />);
      expect(rendered).toMatchSnapshot();
    });

    it("renders for single round", () => {
      useGameConfig.mockReturnValue({
        rounds: 1,
        timer: 300,
      });
      const rendered = shallow(<GameInfo />);
      expect(rendered).toMatchSnapshot();
    });

    it("renders for COUNTRY_RACE", () => {
      useGameConfig.mockReturnValue({
        rounds: 5,
        timer: 300,
        ruleSet: COUNTRY_RACE,
      });
      const rendered = shallow(<GameInfo />);
      expect(rendered).toMatchSnapshot();
    });

    it("renders for FROZEN", () => {
      useGameConfig.mockReturnValue({
        rounds: 5,
        timer: 300,
        ruleSet: FROZEN,
      });
      const rendered = shallow(<GameInfo />);
      expect(rendered).toMatchSnapshot();
    });

    it("renders for single round COUNTRY_RACE", () => {
      useGameConfig.mockReturnValue({
        rounds: 1,
        timer: 300,
        ruleSet: COUNTRY_RACE,
      });
      const rendered = shallow(<GameInfo />);
      expect(rendered).toMatchSnapshot();
    });

    it("renders for single round FROZEN", () => {
      useGameConfig.mockReturnValue({
        rounds: 1,
        timer: 300,
        ruleSet: FROZEN,
      });
      const rendered = shallow(<GameInfo />);
      expect(rendered).toMatchSnapshot();
    });

    it("renders for TIME_BANK", () => {
      useGameConfig.mockReturnValue({
        rounds: 5,
        timer: 300,
        ruleSet: TIME_BANK,
      });
      const rendered = shallow(<GameInfo />);
      expect(rendered).toMatchSnapshot();
    });

    it("renders for RACE", () => {
      useGameConfig.mockReturnValue({
        rounds: 5,
        timer: 300,
        ruleSet: RACE,
      });
      const rendered = shallow(<GameInfo />);
      expect(rendered).toMatchSnapshot();
    });

    it("renders for NORMAL", () => {
      useGameConfig.mockReturnValue({
        rounds: 5,
        timer: 300,
        ruleSet: NORMAL,
      });
      const rendered = shallow(<GameInfo />);
      expect(rendered).toMatchSnapshot();
    });

    it("renders with country lock", () => {
      iso.whereAlpha2.mockReturnValue({ country: "test-country" });
      useGameConfig.mockReturnValue({
        rounds: 5,
        timer: 300,
        countryLock: "country",
      });
      const rendered = shallow(<GameInfo />);
      expect(rendered).toMatchSnapshot();
    });
  });

  describe("PlayerList", () => {
    it("renders", () => {
      const playerNames = ["foo", "bar"];
      const rendered = shallow(<PlayerList playerNames={playerNames} />);
      expect(rendered).toMatchSnapshot();
    });
  });
});
