import {
  getCaretDownSvg,
  getCaretUpSvg,
  getHoveredCaretDownSvg,
  getPivotIconSvg,
  getThemeCheckboxCheckedSvg,
  getThemeCheckboxUncheckedHoveredSvg,
  getThemeCheckboxUncheckedSvg,
  ICONS,
} from "../components/icons/icons";
import {
  GRID_ICON_EDGE_LENGTH,
  GRID_ICON_MARGIN,
  MIN_CF_ICON_MARGIN,
  PIVOT_COLLAPSE_ICON_SIZE,
  PIVOT_INDENT,
} from "../constants";
import { deepEquals } from "../helpers/misc";
import { DEFAULT_PIVOT_STYLE, togglePivotCollapse } from "../helpers/pivot/pivot_helpers";
import { computeTextFontSizeInPixels } from "../helpers/text_helper";
import { Getters } from "../types/getters";
import { ImageSVG } from "../types/image";
import { Align, CellPosition } from "../types/misc";
import { SpreadsheetChildEnv } from "../types/spreadsheet_env";
import { Registry } from "./registry";

export type IconsOfCell = Record<Exclude<Align, undefined>, GridIcon | undefined>;

export interface GridIcon {
  type: string;
  position: CellPosition;
  horizontalAlign: Exclude<Align, undefined>;
  size: number;
  margin: number;
  svg?: ImageSVG;
  hoverSvg?: ImageSVG;
  priority: number;
  onClick?: (position: CellPosition, env: SpreadsheetChildEnv) => void;
}

type ImageSvgCallback = (getters: Getters, position: CellPosition) => GridIcon | undefined;

/**
 * Registry to draw icons on cells
 */
export const iconsOnCellRegistry = new Registry<ImageSvgCallback>();

iconsOnCellRegistry.add("data_validation_checkbox", (getters, position) => {
  const hasIcon = getters.isCellValidCheckbox(position);
  if (hasIcon) {
    const value = !!getters.getEvaluatedCell(position).value;
    const isDark = getters.isDarkMode();
    let svg: ImageSVG;
    let hoverSvg: ImageSVG;
    if (value) {
      svg = getThemeCheckboxCheckedSvg(isDark);
      hoverSvg = getThemeCheckboxCheckedSvg(isDark);
    } else {
      svg = getThemeCheckboxUncheckedSvg(isDark);
      hoverSvg = getThemeCheckboxUncheckedHoveredSvg(isDark);
    }
    return {
      svg,
      hoverSvg,
      priority: 2,
      horizontalAlign: "center",
      size: GRID_ICON_EDGE_LENGTH,
      margin: GRID_ICON_MARGIN,
      position,
      type: "data_validation_checkbox",
      onClick: (position, env) => {
        const cell = env.model.getters.getCell(position);
        const isDisabled = env.model.getters.isReadonly() || !!cell?.isFormula;
        if (isDisabled) {
          return;
        }

        const cellContent = value ? "FALSE" : "TRUE";
        env.model.dispatch("UPDATE_CELL", { ...position, content: cellContent });
      },
    };
  }
  return undefined;
});

iconsOnCellRegistry.add("data_validation_list_chip_icon", (getters, position) => {
  if (getters.isReadonly()) {
    return;
  }
  const chipStyle = getters.getDataValidationChipStyle(position);
  const listIcon = getters.cellHasListDataValidationIcon(position);
  if (!listIcon && !chipStyle) {
    return;
  }
  const cellStyle = getters.getCellComputedStyle(position);
  const iconStyle = chipStyle ? chipStyle : cellStyle;
  return {
    svg: getCaretDownSvg(iconStyle),
    hoverSvg: getHoveredCaretDownSvg(iconStyle),
    priority: 2,
    horizontalAlign: "right",
    size: computeTextFontSizeInPixels(cellStyle),
    margin: 4,
    position,
    onClick: (position, env) => {
      const { col, row } = position;
      env.model.selection.selectCell(col, row);
      env.startCellEdition();
    },
    type: "data_validation_list_chip_icon",
  };
});

iconsOnCellRegistry.add("conditional_formatting", (getters, position) => {
  const icon = getters.getConditionalIcon(position);
  if (icon) {
    const style = getters.getCellStyle(position);
    return {
      type: "conditional_formatting",
      svg: ICONS[icon].svg,
      priority: 1,
      horizontalAlign: "left",
      size: computeTextFontSizeInPixels(style),
      margin: MIN_CF_ICON_MARGIN,
      position,
    };
  }
  return undefined;
});

iconsOnCellRegistry.add("pivot_collapse", (getters, position) => {
  const pivotId = getters.getPivotIdFromPosition(position);
  if (!getters.isSpillPivotFormula(position) || !pivotId) {
    return undefined;
  }
  const pivotCell = getters.getPivotCellFromPosition(position);
  const definition = getters.getPivotCoreDefinition(pivotId);
  const tabularForm = definition.style?.tabularForm ?? DEFAULT_PIVOT_STYLE.tabularForm;

  if (!tabularForm && pivotCell.type === "HEADER" && pivotId && pivotCell.domain.length) {
    const isDashboard = getters.isDashboard();

    const fields = pivotCell.dimension === "COL" ? definition.columns : definition.rows;
    const hasIcon =
      !isDashboard && !getters.shouldShowFormulas() && pivotCell.domain.length !== fields.length;

    const domains = definition.collapsedDomains?.[pivotCell.dimension] ?? [];
    const isCollapsed = domains.some((domain) => deepEquals(domain, pivotCell.domain));

    const indent = pivotCell.dimension === "ROW" ? (pivotCell.domain.length - 1) * PIVOT_INDENT : 0;
    return {
      type: "pivot_collapse",
      priority: 4,
      horizontalAlign: "left",
      size:
        hasIcon || (!isDashboard && pivotCell.dimension === "ROW" && definition.rows.length > 1)
          ? PIVOT_COLLAPSE_ICON_SIZE
          : 0,
      margin: hasIcon ? GRID_ICON_MARGIN * 2 + indent : indent,
      svg: hasIcon ? getPivotIconSvg(isCollapsed, false) : undefined,
      hoverSvg: hasIcon ? getPivotIconSvg(isCollapsed, true) : undefined,
      position,
      onClick: togglePivotCollapse,
    };
  }
  return undefined;
});

iconsOnCellRegistry.add("pivot_dashboard_sorting", (getters, position) => {
  if (!getters.isDashboard()) {
    return undefined;
  }
  const pivotCell = getters.getPivotCellFromPosition(position);
  if (pivotCell.type !== "MEASURE_HEADER") {
    return undefined;
  }
  const sortDirection = getters.getPivotCellSortDirection(position);
  if (sortDirection !== "asc" && sortDirection !== "desc") {
    return undefined;
  }
  const cellStyle = getters.getCellComputedStyle(position);
  return {
    type: `pivot_dashboard_sorting_${sortDirection}`,
    priority: 5,
    horizontalAlign: "right",
    size: computeTextFontSizeInPixels(cellStyle),
    margin: 0,
    svg: sortDirection === "asc" ? getCaretUpSvg(cellStyle) : getCaretDownSvg(cellStyle),
    position,
    onClick: undefined, // click is managed by ClickableCellSortIcon
  };
});
