import { pressKey, simulateTimeline, startTimeline } from "@jspsych/test-utils";

import categorizeAnimation from ".";

jest.useFakeTimers();

describe("categorize-animation plugin", () => {
  test("displays stimulus every 500ms", async () => {
    const { getHTML } = await startTimeline([
      {
        type: categorizeAnimation,
        stimuli: ["img/happy_face_1.jpg", "img/sad_face_1.jpg"],
        key_answer: "d",
        render_on_canvas: false,
      },
    ]);

    expect(getHTML()).toEqual(
      '<img src="img/happy_face_1.jpg" class="jspsych-categorize-animation-stimulus">'
    );
    jest.advanceTimersByTime(500);
    expect(getHTML()).toEqual(
      '<img src="img/sad_face_1.jpg" class="jspsych-categorize-animation-stimulus">'
    );
  });

  test("no delay before first image (tests #1885)", async () => {
    const { getHTML } = await startTimeline([
      {
        type: categorizeAnimation,
        stimuli: ["img/happy_face_1.jpg", "img/sad_face_1.jpg"],
        key_answer: "d",
        render_on_canvas: false,
      },
    ]);

    expect(getHTML()).toEqual(
      '<img src="img/happy_face_1.jpg" class="jspsych-categorize-animation-stimulus">'
    );
    jest.advanceTimersByTime(500);
    expect(getHTML()).toEqual(
      '<img src="img/sad_face_1.jpg" class="jspsych-categorize-animation-stimulus">'
    );
  });

  test("prompt should display after animation", async () => {
    const { getHTML } = await startTimeline([
      {
        type: categorizeAnimation,
        stimuli: ["img/happy_face_1.jpg", "img/sad_face_1.jpg"],
        key_answer: "d",
        prompt:
          "<p>Press d if the faces had different emotional expressions. Press S if the faces had the same emotional expression.</p>",
        render_on_canvas: false,
      },
    ]);

    jest.advanceTimersByTime(1000);
    expect(getHTML()).toEqual(
      "<p>Press d if the faces had different emotional expressions. Press S if the faces had the same emotional expression.</p>"
    );
  });

  test("should display correct if key_answer is pressed", async () => {
    const { getHTML } = await startTimeline([
      {
        type: categorizeAnimation,
        stimuli: ["img/happy_face_1.jpg", "img/sad_face_1.jpg"],
        key_answer: "d",
        choices: ["d", "s"],
        prompt:
          "<p>Press d if the faces had different emotional expressions. Press S if the faces had the same emotional expression.</p>",
        render_on_canvas: false,
      },
    ]);

    jest.advanceTimersByTime(1000);
    await pressKey("d");
    jest.advanceTimersByTime(1000);
    expect(getHTML()).toBe("Correct.");
  });

  test("should display incorrect if different key is pressed", async () => {
    const { getHTML } = await startTimeline([
      {
        type: categorizeAnimation,
        stimuli: ["img/happy_face_1.jpg", "img/sad_face_1.jpg"],
        key_answer: "d",
        choices: ["d", "s"],
        prompt:
          "<p>Press d if the faces had different emotional expressions. Press S if the faces had the same emotional expression.</p>",
        render_on_canvas: false,
      },
    ]);

    jest.advanceTimersByTime(1000);
    await pressKey("s");
    jest.advanceTimersByTime(1000);
    expect(getHTML()).toBe("Wrong.");
  });

  test("text answer should replace %ANS%", async () => {
    const { getHTML } = await startTimeline([
      {
        type: categorizeAnimation,
        stimuli: ["img/happy_face_1.jpg", "img/sad_face_3.jpg"],
        key_answer: "d",
        choices: ["d", "s"],
        text_answer: "different",
        correct_text: "<p>Correct. The faces had %ANS% expressions.</p>",
        incorrect_text: "<p>Incorrect. The faces had %ANS% expressions.</p>",
        prompt:
          "<p>Press D if the faces had different emotional expressions. Press S if the faces had the same emotional expression.</p>",
        render_on_canvas: false,
      },
    ]);

    jest.advanceTimersByTime(1000);
    await pressKey("d");
    jest.advanceTimersByTime(1000);
    expect(getHTML()).toBe("<p>Correct. The faces had different expressions.</p>");
  });

  test("correct text displays when when key_answer is pressed", async () => {
    const { getHTML } = await startTimeline([
      {
        type: categorizeAnimation,
        stimuli: ["img/happy_face_1.jpg", "img/sad_face_3.jpg"],
        key_answer: "d",
        choices: ["d", "s"],
        correct_text: "<p>You pressed the correct key</p>",
        incorrect_text: "<p>Incorrect.</p>",
        prompt:
          "<p>Press D if the faces had different emotional expressions. Press S if the faces had the same emotional expression.</p>",
        render_on_canvas: false,
      },
    ]);

    jest.advanceTimersByTime(1000);
    await pressKey("d");
    jest.advanceTimersByTime(1000);
    expect(getHTML()).toBe("<p>You pressed the correct key</p>");
  });

  test("incorrect text displays when not key_answer is pressed", async () => {
    const { getHTML } = await startTimeline([
      {
        type: categorizeAnimation,
        stimuli: ["img/happy_face_1.jpg", "img/sad_face_3.jpg"],
        key_answer: "d",
        choices: ["d", "s"],
        correct_text: "<p>You pressed the correct key</p>",
        incorrect_text: "<p>Incorrect. You pressed the wrong key.</p>",
        prompt:
          "<p>Press D if the faces had different emotional expressions. Press S if the faces had the same emotional expression.</p>",
        render_on_canvas: false,
      },
    ]);

    jest.advanceTimersByTime(1500);
    await pressKey("s");
    jest.advanceTimersByTime(1000);
    expect(getHTML()).toBe("<p>Incorrect. You pressed the wrong key.</p>");
  });

  test("duration to display image is based on frame_time", async () => {
    const { getHTML } = await startTimeline([
      {
        type: categorizeAnimation,
        stimuli: ["img/happy_face_1.jpg", "img/sad_face_1.jpg"],
        key_answer: "d",
        choices: ["d", "s"],
        frame_time: 1000,
        correct_text: "<p>You pressed the correct key</p>",
        incorrect_text: "<p>Incorrect. You pressed the wrong key.</p>",
        prompt:
          "<p>Press D if the faces had different emotional expressions. Press S if the faces had the same emotional expression.</p>",
        render_on_canvas: false,
      },
    ]);

    expect(getHTML()).toEqual(
      '<img src="img/happy_face_1.jpg" class="jspsych-categorize-animation-stimulus">'
    );
    jest.advanceTimersByTime(500);
    expect(getHTML()).toEqual(
      '<img src="img/happy_face_1.jpg" class="jspsych-categorize-animation-stimulus">'
    );
    jest.advanceTimersByTime(500);
    expect(getHTML()).toEqual(
      '<img src="img/sad_face_1.jpg" class="jspsych-categorize-animation-stimulus">'
    );
  });

  test("sequence reps", async () => {
    const { getHTML } = await startTimeline([
      {
        type: categorizeAnimation,
        stimuli: ["img/happy_face_1.jpg", "img/sad_face_1.jpg"],
        key_answer: "d",
        choices: ["d", "s"],
        frame_time: 1000,
        sequence_reps: 2,
        correct_text: "<p>You pressed the correct key</p>",
        incorrect_text: "<p>Incorrect. You pressed the wrong key.</p>",
        prompt:
          "<p>Press D if the faces had different emotional expressions. Press S if the faces had the same emotional expression.</p>",
        render_on_canvas: false,
      },
    ]);

    for (let i = 0; i < 2; i++) {
      expect(getHTML()).toEqual(
        '<img src="img/happy_face_1.jpg" class="jspsych-categorize-animation-stimulus">'
      );
      jest.advanceTimersByTime(1000);
      expect(getHTML()).toEqual(
        '<img src="img/sad_face_1.jpg" class="jspsych-categorize-animation-stimulus">'
      );
      jest.advanceTimersByTime(1000);
    }
  });

  test("subject can response before animation is completed", async () => {
    const { getHTML } = await startTimeline([
      {
        type: categorizeAnimation,
        stimuli: ["img/happy_face_1.jpg", "img/sad_face_1.jpg"],
        key_answer: "d",
        choices: ["d", "s"],
        frame_time: 1000,
        sequence_reps: 2,
        correct_text: "<p>You pressed the correct key</p>",
        incorrect_text: "<p>Incorrect. You pressed the wrong key.</p>",
        prompt:
          "<p>Press D if the faces had different emotional expressions. Press S if the faces had the same emotional expression.</p>",
        allow_response_before_complete: true,
        render_on_canvas: false,
      },
    ]);

    jest.advanceTimersByTime(500);
    await pressKey("d");
    jest.advanceTimersByTime(1000);
    expect(getHTML()).toEqual(
      '<img src="img/sad_face_1.jpg" class="jspsych-categorize-animation-stimulus"><p>You pressed the correct key</p>'
    );
  });

  test("display should clear after feeback_duration is done", async () => {
    const { getHTML, expectFinished } = await startTimeline([
      {
        type: categorizeAnimation,
        stimuli: ["img/happy_face_1.jpg", "img/sad_face_1.jpg"],
        key_answer: "d",
        choices: ["d", "s"],
        frame_time: 500,
        feeback_duration: 500,
        correct_text: "<p>You pressed the correct key</p>",
        incorrect_text: "<p>Incorrect. You pressed the wrong key.</p>",
        prompt:
          "<p>Press D if the faces had different emotional expressions. Press S if the faces had the same emotional expression.</p>",
        render_on_canvas: false,
      },
    ]);

    jest.advanceTimersByTime(1000);
    await pressKey("d");
    jest.advanceTimersByTime(500);
    expect(getHTML()).toBe("<p>You pressed the correct key</p>");
    jest.advanceTimersByTime(2000);

    await expectFinished();
  });
});

describe("categorize-animation plugin simulation", () => {
  test("data-only mode works", async () => {
    const { getData, expectFinished } = await simulateTimeline([
      {
        type: categorizeAnimation,
        stimuli: ["img/happy_face_1.jpg", "img/sad_face_1.jpg"],
        frame_time: 500,
        key_answer: "d",
        render_on_canvas: false,
      },
    ]);

    await expectFinished();
    expect(getData().values()[0].rt).toBeGreaterThan(1000);
  });

  test("visual mode works", async () => {
    const { getData, expectRunning, expectFinished } = await simulateTimeline(
      [
        {
          type: categorizeAnimation,
          stimuli: ["img/happy_face_1.jpg", "img/sad_face_1.jpg"],
          frame_time: 500,
          key_answer: "d",
          render_on_canvas: false,
        },
      ],
      "visual"
    );

    await expectRunning();

    jest.runAllTimers();

    await expectFinished();

    expect(getData().values()[0].rt).toBeGreaterThan(1000);
  });
});
