import { Model, UID } from "../../src";
import { CellComposerStore } from "../../src/components/composer/composer/cell_composer_store";
import { Grid } from "../../src/components/grid/grid";
import { DEFAULT_CELL_HEIGHT, DEFAULT_CELL_WIDTH } from "../../src/constants";
import { toZone, zoneToXc } from "../../src/helpers/zones";
import { SpreadsheetChildEnv } from "../../src/types/spreadsheet_env";
import { createDynamicTable, createTable, setCellContent } from "../test_helpers/commands_helpers";
import { clickAndDrag, triggerMouseEvent } from "../test_helpers/dom_helper";
import { getCellRawContent } from "../test_helpers/getters_helpers";
import {
  flattenHighlightRange,
  getHighlightsFromStore,
  mountComponent,
  nextTick,
} from "../test_helpers/helpers";
import { extendMockGetBoundingClientRect } from "../test_helpers/mock_helpers";

extendMockGetBoundingClientRect({
  "o-spreadsheet": () => {
    return { x: 0, y: 0, width: 1000, height: 1000 };
  },
  "o-grid": () => {
    return { x: 0, y: 0, width: 1000, height: 780 };
  },
  "o-spreadsheet-bottombar-wrapper": () => {
    return { x: 0, y: 0, width: 1000, height: 120 };
  },
  "o-spreadsheet-topbar-wrapper": () => {
    return { x: 0, y: 0, width: 1000, height: 100 };
  },
});
describe("Table resizer component", () => {
  let model: Model;
  let sheetId: UID;
  let env: SpreadsheetChildEnv;

  beforeEach(async () => {
    ({ env, model } = await mountComponent(Grid, {
      props: {
        exposeFocus: () => {},
        getGridSize: () => ({ width: 1000, height: 1000 }),
      },
    }));
    sheetId = model.getters.getActiveSheetId();
  });

  test("Can resize a table with drag & drop", async () => {
    createTable(model, "A1:B2");
    await nextTick();

    let dragEndPosition = { x: DEFAULT_CELL_WIDTH * 4, y: DEFAULT_CELL_HEIGHT * 4 };
    await clickAndDrag(".o-table-resizer", dragEndPosition, undefined, true);
    expect(zoneToXc(model.getters.getTables(sheetId)[0].range.zone)).toEqual("A1:E5");

    dragEndPosition = { x: DEFAULT_CELL_WIDTH * 2, y: DEFAULT_CELL_HEIGHT * 2 };
    await clickAndDrag(".o-table-resizer", dragEndPosition, undefined, true);
    expect(zoneToXc(model.getters.getTables(sheetId)[0].range.zone)).toEqual("A1:C3");
  });

  test("Highlight appear during the table drag & drop", async () => {
    createTable(model, "A1:B2");
    await nextTick();
    const dragEndPosition = { x: DEFAULT_CELL_WIDTH * 4, y: DEFAULT_CELL_HEIGHT * 4 };
    await clickAndDrag(".o-table-resizer", dragEndPosition, undefined, false);
    expect(flattenHighlightRange(getHighlightsFromStore(env)[0])).toMatchObject({
      zone: toZone("A1:E5"),
      noFill: true,
    });

    triggerMouseEvent(".o-table-resizer", "pointerup", 0, 0);
    expect(getHighlightsFromStore(env)[0]).toEqual(undefined);
  });

  test("Cannot drag & drop to position above/left of the table", async () => {
    createTable(model, "C3:D4");
    await nextTick();

    await clickAndDrag(".o-table-resizer", { x: 0, y: 0 }, undefined, false);
    expect(flattenHighlightRange(getHighlightsFromStore(env)[0])).toMatchObject({
      zone: toZone("C3"),
    });
    triggerMouseEvent(".o-table-resizer", "pointerup", 0, 0);
    expect(zoneToXc(model.getters.getTables(sheetId)[0].range.zone)).toEqual("C3");
  });

  test("Table formula are auto-filled on resize table down", async () => {
    createTable(model, "A1:B2");
    setCellContent(model, "A2", "=A1+1");
    setCellContent(model, "B2", "string content");
    await nextTick();

    const dragEndPosition = { x: DEFAULT_CELL_WIDTH, y: DEFAULT_CELL_HEIGHT * 2 };
    await clickAndDrag(".o-table-resizer", dragEndPosition, undefined, true);

    expect(zoneToXc(model.getters.getTables(sheetId)[0].range.zone)).toEqual("A1:B3");
    expect(getCellRawContent(model, "A3")).toEqual("=A2+1");
    expect(getCellRawContent(model, "B3")).toBeUndefined();
  });

  test("Cannot resize a dynamic table", async () => {
    setCellContent(model, "A1", "=MUNIT(5)");
    createDynamicTable(model, "A1");
    await nextTick();

    expect(document.querySelector(".o-table-resizer")).toBeNull();
  });

  test("Table resizer is not loaded in readonly mode", async () => {
    createTable(model, "A1:B2");
    await nextTick();
    expect(".o-table-resizer").toHaveCount(1);
    model.updateMode("readonly");
    await nextTick();
    expect(".o-table-resizer").toHaveCount(0);
  });

  test("table resizer is not loaded when the grid selection is not active", async () => {
    createTable(model, "A1:B2");
    await nextTick();
    expect(".o-table-resizer").toHaveCount(1);
    // start the edition and steal the selection from the grid
    env.getStore(CellComposerStore).startEdition();
    await nextTick();
    expect(".o-table-resizer").toHaveCount(0);
  });
});
