import { act, renderHook } from "@testing-library/react-hooks";
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils/playerManager";

import { ON_HOLD_INTERVAL, SEEK_TYPE, SKIP_TIME_BASE } from "../const";

import { useAutoSeek } from "../useAutoSeek";

jest.useFakeTimers();

const rewind = jest.fn();
const forward = jest.fn();

jest
  .spyOn(playerManager, "getInstanceController")
  // @ts-ignore
  .mockImplementation(() => ({ rewind, forward }));

describe("useAutoSeek", () => {
  beforeEach(() => {
    rewind.mockReset();
    forward.mockReset();
  });

  describe("autoSeekStart", () => {
    it("should call forward method on playerInstance", () => {
      const { result } = renderHook(() => useAutoSeek());

      act(() => {
        result.current.autoSeekStart(SEEK_TYPE.FORWARD);
      });

      expect(forward).toBeCalled();
      result.current.autoSeekStop();
    });

    it("should call rewind method on playerManager", () => {
      const { result } = renderHook(() => useAutoSeek());

      act(() => {
        result.current.autoSeekStart(SEEK_TYPE.REWIND);
      });

      expect(rewind).toBeCalled();
      result.current.autoSeekStop();
    });

    it("should call rewind with default skip time", () => {
      const { result } = renderHook(() => useAutoSeek());

      act(() => {
        result.current.autoSeekStart(SEEK_TYPE.REWIND);
      });

      expect(rewind).toBeCalledWith(SKIP_TIME_BASE);
      result.current.autoSeekStop();
    });

    it("should call forward with default skip time", () => {
      const { result } = renderHook(() => useAutoSeek());

      act(() => {
        result.current.autoSeekStart(SEEK_TYPE.FORWARD);
      });

      expect(forward).toBeCalledWith(SKIP_TIME_BASE);
      result.current.autoSeekStop();
    });

    it("should call rewind in intervals set in configuration", () => {
      const { result } = renderHook(() => useAutoSeek());

      act(() => {
        result.current.autoSeekStart(SEEK_TYPE.REWIND);
      });

      expect(rewind).toBeCalled();
      jest.advanceTimersByTime(ON_HOLD_INTERVAL * 3);
      expect(rewind).toBeCalledTimes(4);
      result.current.autoSeekStop();
    });

    it("should call forward in intervals set in configuration", () => {
      const { result } = renderHook(() => useAutoSeek());

      act(() => {
        result.current.autoSeekStart(SEEK_TYPE.FORWARD);
      });

      expect(forward).toBeCalled();
      jest.advanceTimersByTime(ON_HOLD_INTERVAL * 3);
      expect(forward).toBeCalledTimes(4);
      result.current.autoSeekStop();
    });
  });

  describe("autoSeekStop", () => {
    it("should stop calling playerManager method after autoSeekStop is called", () => {
      const { result } = renderHook(() => useAutoSeek());

      act(() => {
        result.current.autoSeekStart(SEEK_TYPE.FORWARD);
      });

      expect(forward).toBeCalled();
      jest.advanceTimersByTime(ON_HOLD_INTERVAL * 3);
      expect(forward).toBeCalledTimes(4);

      act(() => {
        result.current.autoSeekStop();
      });

      jest.advanceTimersByTime(ON_HOLD_INTERVAL * 3);
      expect(forward).toBeCalledTimes(4);
    });
  });
});
