import { CarouselPanel } from "../components/side_panel/carousel_panel/carousel_panel";
import { ChartPanel } from "../components/side_panel/chart/main_chart_panel/main_chart_panel";
import { ColumnStatsPanel } from "../components/side_panel/column_stats/column_stats_panel";
import { ConditionalFormattingEditor } from "../components/side_panel/conditional_formatting/cf_editor/cf_editor";
import { ConditionalFormatPreviewList } from "../components/side_panel/conditional_formatting/cf_preview_list/cf_preview_list";
import { DataAnalysisPanel } from "../components/side_panel/data_analysis/data_analysis_panel";
import { DataSourcesCleanup } from "../components/side_panel/data_sources_cleanup/data_sources_cleanup";
import { DataValidationPanel } from "../components/side_panel/data_validation/data_validation_panel";
import { DataValidationEditor } from "../components/side_panel/data_validation/dv_editor/dv_editor";
import { FindAndReplacePanel } from "../components/side_panel/find_and_replace/find_and_replace";
import { MoreFormatsPanel } from "../components/side_panel/more_formats/more_formats";
import { NamedRangesPanel } from "../components/side_panel/named_ranges_panel/named_ranges_panel";
import { PerfProfilePanel } from "../components/side_panel/perf_profile/perf_profile_panel";
import { PivotMeasureDisplayPanel } from "../components/side_panel/pivot/pivot_measure_display_panel/pivot_measure_display_panel";
import { PivotSidePanel } from "../components/side_panel/pivot/pivot_side_panel/pivot_side_panel";
import { RemoveDuplicatesPanel } from "../components/side_panel/remove_duplicates/remove_duplicates";
import { SettingsPanel } from "../components/side_panel/settings/settings_panel";
import { SidePanelState } from "../components/side_panel/side_panel/side_panel_store";
import { SplitIntoColumnsPanel } from "../components/side_panel/split_to_columns_panel/split_to_columns_panel";
import { TablePanel } from "../components/side_panel/table_panel/table_panel";
import { TableStyleEditorPanel } from "../components/side_panel/table_style_editor_panel/table_style_editor_panel";
import { _t } from "../translation";
import { ConditionalFormat } from "../types/conditional_formatting";
import { Getters } from "../types/getters";
import { UID } from "../types/misc";
import { PropsOf } from "../types/props_of";
import { SpreadsheetChildEnv } from "../types/spreadsheet_env";
import { Registry } from "./registry";

//------------------------------------------------------------------------------
// Side Panel Registry
//------------------------------------------------------------------------------

export interface SidePanelContent {
  title: string | ((env: SpreadsheetChildEnv, props: object) => string);
  Body: any;
  Footer?: any;
  /**
   * A callback used to validate the props or generate new props
   * based on the current state of the spreadsheet model, using the getters.
   */
  computeState?: (getters: Getters, initialProps: object) => SidePanelState;
}

export const sidePanelRegistry = new Registry<SidePanelContent>();

sidePanelRegistry.add("ConditionalFormatting", {
  title: _t("Conditional formatting"),
  Body: ConditionalFormatPreviewList,
});

sidePanelRegistry.add("ConditionalFormattingEditor", {
  title: _t("Conditional formatting"),
  Body: ConditionalFormattingEditor,
  computeState: (getters: Getters, props: { cf: ConditionalFormat }) => {
    return {
      isOpen: true,
      props,
      key: `ConditionalFormattingEditor_${props.cf.id}`,
    };
  },
});

sidePanelRegistry.add("ChartPanel", {
  title: _t("Chart"),
  Body: ChartPanel,
  computeState: (getters: Getters, initialProps: { chartId: UID }) => {
    const figureIds = getters.getSelectedFigureIds();
    if (figureIds.length > 1) {
      return { isOpen: false };
    }
    const figureId = figureIds.length && figureIds[0];
    const sheetId = figureId && getters.getFigureSheetId(figureId);
    const isSheetLocked = sheetId ? getters.isSheetLocked(sheetId) : false;
    const chartId = figureId ? getters.getChartIdFromFigureId(figureId) : initialProps.chartId;
    if (!chartId || !getters.isChartDefined(chartId) || isSheetLocked) {
      return { isOpen: false };
    }
    return { isOpen: true, props: { chartId } };
  },
});

sidePanelRegistry.add("FindAndReplace", {
  title: _t("Find and Replace"),
  Body: FindAndReplacePanel,
});

sidePanelRegistry.add("SplitToColumns", {
  title: _t("Split text into columns"),
  Body: SplitIntoColumnsPanel,
});

sidePanelRegistry.add("Settings", {
  title: _t("Spreadsheet settings"),
  Body: SettingsPanel,
});

sidePanelRegistry.add("RemoveDuplicates", {
  title: _t("Remove duplicates"),
  Body: RemoveDuplicatesPanel,
});

sidePanelRegistry.add("DataSourceCleanup", {
  title: _t("Unused data sources"),
  Body: DataSourcesCleanup,
});

sidePanelRegistry.add("DataValidation", {
  title: _t("Data validation"),
  Body: DataValidationPanel,
});

sidePanelRegistry.add("DataValidationEditor", {
  title: _t("Data validation"),
  Body: DataValidationEditor,
  computeState: (getters: Getters, props: { ruleId: UID }) => {
    return {
      isOpen: true,
      props,
      key: `DataValidationEditor_${props.ruleId}`,
    };
  },
});

sidePanelRegistry.add("MoreFormats", {
  title: _t("More formats"),
  Body: MoreFormatsPanel,
});

sidePanelRegistry.add("ColumnStats", {
  title: _t("Column statistics"),
  Body: ColumnStatsPanel,
});

sidePanelRegistry.add("DataAnalysisPanel", {
  title: _t("Data analysis"),
  Body: DataAnalysisPanel,
});

sidePanelRegistry.add("TableSidePanel", {
  title: _t("Edit table"),
  Body: TablePanel,
  computeState: (getters: Getters, props: PropsOf<TablePanel>) => {
    const sheetId = props.table.range.sheetId;
    const table = getters.getCoreTableById(sheetId, props.table.id);
    if (sheetId !== getters.getActiveSheetId() || !table) {
      return { isOpen: false };
    }
    return { isOpen: true, props: { ...props, table }, key: props.table.id };
  },
});

sidePanelRegistry.add("TableStyleEditorPanel", {
  title: _t("Create custom table style"),
  Body: TableStyleEditorPanel,
  computeState: (getters: Getters, initialProps: PropsOf<TableStyleEditorPanel>) => {
    return {
      isOpen: true,
      props: { ...initialProps },
      key: initialProps.styleId ?? "new",
    };
  },
});

sidePanelRegistry.add("PivotSidePanel", {
  title: (env: SpreadsheetChildEnv, props: { pivotId: UID }) => {
    return _t("Pivot #%s", env.model.getters.getPivotFormulaId(props.pivotId));
  },
  Body: PivotSidePanel,
  computeState: (getters: Getters, props: { pivotId: UID }) => {
    return {
      isOpen: getters.isExistingPivot(props.pivotId),
      props,
      key: `pivot_key_${props.pivotId}`,
    };
  },
});

sidePanelRegistry.add("PivotMeasureDisplayPanel", {
  title: (env: SpreadsheetChildEnv, props: PropsOf<PivotMeasureDisplayPanel>) => {
    const measure = env.model.getters.getPivot(props.pivotId).getMeasure(props.measure.id);
    return _t('Measure "%s" options', measure.displayName);
  },
  Body: PivotMeasureDisplayPanel,
  computeState: (getters: Getters, props: PropsOf<PivotMeasureDisplayPanel>) => {
    try {
      // This will throw if the pivot or measure does not exist
      getters.getPivot(props.pivotId).getMeasure(props.measure.id);
      return {
        isOpen: true,
        props,
        key: `pivot_measure_display_${props.pivotId}_${props.measure.id}`,
      };
    } catch (e) {
      return { isOpen: false };
    }
  },
});

sidePanelRegistry.add("CarouselPanel", {
  title: _t("Carousel"),
  Body: CarouselPanel,
  computeState: (getters: Getters, initialProps: { figureId: UID }) => {
    const figureId =
      initialProps.figureId ||
      (getters.getSelectedFigureIds().length && getters.getSelectedFigureIds()[0]);
    const sheetId = figureId && getters.getFigureSheetId(figureId);
    const isSheetLocked = sheetId ? getters.isSheetLocked(sheetId) : false;
    if (!figureId || !getters.doesCarouselExist(figureId) || isSheetLocked) {
      return { isOpen: false };
    }

    return { isOpen: true, props: { figureId } };
  },
});

sidePanelRegistry.add("NamedRangesPanel", {
  title: _t("Named Ranges"),
  Body: NamedRangesPanel,
});

sidePanelRegistry.add("PerfProfile", {
  title: _t("Performance"),
  Body: PerfProfilePanel,
});
