import { shallow } from "enzyme";
import React from "react";
import GameCreationForm from "../components/util/GameCreationForm";
import { LastSettingsButton } from "../components/util/GameCreationForm/GameCreationForm";
import { createGame } from "../domain/apiMethods";
import { COUNTRY_RACE, FROZEN, NORMAL, URBAN } from "../domain/constants";
import useCountryLookup from "../hooks/useCountryLookup";

jest.mock("../domain/apiMethods");
jest.mock("../hooks/useCountryLookup");

describe("GameCreationForm", () => {
  it("renders", () => {
    useCountryLookup.mockReturnValue("country-lookup");
    const afterCreate = jest.fn();
    const rendered = shallow(<GameCreationForm afterCreate={afterCreate} />);
    expect(rendered).toMatchSnapshot();
  });

  it("creates a game", async () => {
    useCountryLookup.mockReturnValue("country-lookup");
    createGame.mockReturnValue("test-game-id");
    const afterCreate = jest.fn();
    const rendered = shallow(<GameCreationForm afterCreate={afterCreate} />);
    await rendered.find("button").first().simulate("click");
    expect(createGame).toHaveBeenCalled();
    expect(afterCreate).toHaveBeenCalledWith("test-game-id");
  });

  it("does nothing after creating a game if no afterCreate given", async () => {
    useCountryLookup.mockReturnValue("country-lookup");
    createGame.mockReturnValue("test-game-id");
    const rendered = shallow(<GameCreationForm />);
    await rendered.find("button").first().simulate("click");
    expect(createGame).toHaveBeenCalled();
  });

  it("handles error creating a game", async () => {
    useCountryLookup.mockReturnValue("country-lookup");
    createGame.mockImplementation(() => {
      throw new Error();
    });
    const afterCreate = jest.fn();
    const rendered = shallow(<GameCreationForm afterCreate={afterCreate} />);
    await rendered.find("button").first().simulate("click");
    expect(createGame).toHaveBeenCalled();
    expect(afterCreate).not.toHaveBeenCalled();
    expect(rendered).toMatchSnapshot();
  });

  it("can have the error modal closed", async () => {
    useCountryLookup.mockReturnValue("country-lookup");
    createGame.mockImplementation(() => {
      throw new Error();
    });
    const rendered = shallow(<GameCreationForm />);
    await rendered.find("button").first().simulate("click");
    rendered.find("ErrorModal").first().prop("onClose")();
    expect(rendered).toMatchSnapshot();
  });

  it("can have the preset dropdown opened", () => {
    useCountryLookup.mockReturnValue("country-lookup");
    const rendered = shallow(<GameCreationForm />);
    rendered.find("Dropdown").first().prop("onClick")();
    expect(rendered).toMatchSnapshot();
  });

  it("can have presets selected", () => {
    useCountryLookup.mockReturnValue("country-lookup");
    const rendered = shallow(<GameCreationForm />);
    rendered.find("Dropdown").first().prop("onSelect")({
      timer: 30,
      rounds: 3,
      countryLock: "us",
      generationMethod: URBAN,
      gameMode: FROZEN,
      clockMode: NORMAL,
      scoreMethod: COUNTRY_RACE,
      roundPointCap: null,
    });
    expect(rendered).toMatchSnapshot();
  });

  it("can have previous game settings passed in to enable reuse button", () => {
    useCountryLookup.mockReturnValue("country-lookup");
    const rendered = shallow(
      <GameCreationForm
        lastSettings={{
          timer: 30,
          rounds: 3,
          countryLock: "us",
          generationMethod: URBAN,
          gameMode: FROZEN,
          clockMode: NORMAL,
          scoreMethod: COUNTRY_RACE,
          roundPointCap: null,
        }}
      />
    );
    expect(rendered).toMatchSnapshot();
    rendered.find("LastSettingsButton").first().prop("onClick")();
    expect(rendered).toMatchSnapshot();
  });

  describe("LastSettingsButton", () => {
    it("renders", () => {
      const onClick = jest.fn();
      const rendered = shallow(<LastSettingsButton onClick={onClick} />);
      expect(rendered).toMatchSnapshot();
    });

    it("responds to click", () => {
      const onClick = jest.fn();
      const rendered = shallow(<LastSettingsButton onClick={onClick} />);
      rendered.simulate("click");
      expect(onClick).toHaveBeenCalled();
    });

    it("responds to keydown Enter", () => {
      const onClick = jest.fn();
      const rendered = shallow(<LastSettingsButton onClick={onClick} />);
      rendered.simulate("keydown", { key: "Enter" });
      expect(onClick).toHaveBeenCalled();
    });

    it("cannot be selected with other keydowns", () => {
      const onClick = jest.fn();
      const rendered = shallow(<LastSettingsButton onClick={onClick} />);
      rendered.simulate("keydown", { key: "Escape" });
      expect(onClick).not.toHaveBeenCalled();
    });
  });
});
