process.env.REACT_APP_MONITOR_STORE = "true";

jest.mock("../store");
jest.mock("../domain/apiMethods");
jest.mock("../domain/localStorageMethods");

import { getCurrentRound, joinGame } from "../domain/apiMethods";
import { IN_ROUND, POST_GAME, PRE_ROUND } from "../domain/gameStates";
import {
  dispatch,
  useGameId,
  usePlayerName,
  useGameState,
  useCurrentRound,
  useTargetPoint,
  usePanoStartPosition,
  usePanoStartPov,
  useRoundSeconds,
} from "../domain/gameStore";
import {
  clearGameInfoFromLocalStorage,
  clearRoundInfoFromLocalStorage,
  saveGameInfoToLocalStorage,
} from "../domain/localStorageMethods";

describe("gameStore", () => {
  beforeEach(() => {
    dispatch.RESET_STORE();
  });
  describe("dispatch", () => {
    describe("setPlayerName", () => {
      it("sets player name", () => {
        dispatch.setPlayerName("test-player-name");
        expect(usePlayerName()).toBe("test-player-name");
      });
    });
    describe("goToLobby", () => {
      it("goes to lobby", () => {
        dispatch.goToLobby("test-game-id");
        expect(useGameId()).toBe("test-game-id");
        expect(dispatch.GET_STORED_VALUE("playerId")).toBe(null);
        expect(useGameState()).toBe(PRE_ROUND);
      });
    });
    describe("startRound", () => {
      it("starts round", () => {
        dispatch.startRound();
        expect(useGameState()).toBe(IN_ROUND);
      });
    });
    describe("goToSummary", () => {
      it("goes to summary", () => {
        dispatch.goToSummary();
        expect(useGameId()).toBe(null);
        expect(useGameState()).toBe(POST_GAME);
        expect(clearRoundInfoFromLocalStorage).toHaveBeenCalled();
        expect(clearGameInfoFromLocalStorage).toHaveBeenCalled();
      });
      it("updates game ID if given", () => {
        dispatch.goToSummary("test-game-id");
        expect(useGameId()).toBe("test-game-id");
        expect(useGameState()).toBe(POST_GAME);
        expect(clearRoundInfoFromLocalStorage).toHaveBeenCalled();
        expect(clearGameInfoFromLocalStorage).toHaveBeenCalled();
      });
      it("can avoid clearing saved data", () => {
        dispatch.goToSummary("test-game-id", false);
        expect(useGameId()).toBe("test-game-id");
        expect(useGameState()).toBe(POST_GAME);
        expect(clearRoundInfoFromLocalStorage).not.toHaveBeenCalled();
        expect(clearGameInfoFromLocalStorage).not.toHaveBeenCalled();
      });
    });
    describe("updateCurrentRound", () => {
      it("updates current round", async () => {
        getCurrentRound.mockReturnValue({
          currentRound: "round",
          coord: "coord",
          timer: "timer",
        });
        await dispatch.updateCurrentRound();
        expect(useCurrentRound()).toBe("round");
        expect(useTargetPoint()).toBe("coord");
        expect(usePanoStartPosition()).toBe("coord");
        expect(usePanoStartPov()).toMatchObject({
          heading: 0,
          pitch: 0,
        });
        expect(useRoundSeconds()).toBe("timer");
        expect(getCurrentRound).toMatchSnapshot();
      });
    });
    describe("joinGame", () => {
      it("joins game then updates current round", async () => {
        dispatch.SET_STORED_VALUE("gameId", "test-game-id");
        dispatch.SET_STORED_VALUE("playerName", "test-player-name");
        joinGame.mockReturnValue({
          playerId: "test-player-id",
        });
        getCurrentRound.mockReturnValue({
          currentRound: "round",
          coord: "coord",
          timer: "timer",
        });
        await dispatch.joinGame();
        expect(joinGame).toMatchSnapshot();
        expect(saveGameInfoToLocalStorage).toMatchSnapshot();
        expect(dispatch.GET_STORED_VALUE("playerId")).toBe("test-player-id");
        expect(useCurrentRound()).toBe("round");
        expect(useTargetPoint()).toBe("coord");
        expect(usePanoStartPosition()).toBe("coord");
        expect(usePanoStartPov()).toMatchObject({
          heading: 0,
          pitch: 0,
        });
        expect(useRoundSeconds()).toBe("timer");
        expect(getCurrentRound).toMatchSnapshot();
      });
    });
  });
});
