import { useProps } from "@odoo/owl";
import { PIVOT_TOKEN_COLOR } from "../../../../../constants";
import { CompiledFormula } from "../../../../../formulas/compiler";
import { Token } from "../../../../../formulas/tokenizer";
import { unquote } from "../../../../../helpers/misc";
import { getFieldDisplayName } from "../../../../../helpers/pivot/pivot_helpers";
import { Component } from "../../../../../owl3_compatibility_layer";
import { createMeasureAutoComplete } from "../../../../../registries/auto_completes/pivot_dimension_auto_complete";
import { _t } from "../../../../../translation";
import { Color, ValueAndLabel } from "../../../../../types/misc";
import { PivotMeasure } from "../../../../../types/pivot";
import { SpreadsheetChildEnv } from "../../../../../types/spreadsheet_env";
import { StandaloneComposer } from "../../../../composer/standalone_composer/standalone_composer";
import { types } from "../../../../props_validation";
import { Select } from "../../../../select/select";
import { measureDisplayTerms } from "../../../../translations_terms";
import { PivotDimension } from "../pivot_dimension/pivot_dimension";

export class PivotMeasureEditor extends Component<SpreadsheetChildEnv> {
  static template = "o-spreadsheet-PivotMeasureEditor";
  static components = {
    PivotDimension,
    StandaloneComposer,
    Select,
  };
  protected props = useProps({
    pivotId: types.string(),
    definition: types.PivotRuntimeDefinition(),
    measure: types.PivotMeasure(),
    onMeasureUpdated: types.function<(measure: PivotMeasure) => void>(),
    onRemoved: types.function(),
    generateMeasureId: types.function<(fieldName: string, aggregator?: string) => string>(),
    aggregators: types.object({}),
  });

  getMeasureAutocomplete() {
    return createMeasureAutoComplete(this.props.definition, this.props.measure);
  }

  updateMeasureFormula(formula: string) {
    this.props.onMeasureUpdated({
      ...this.props.measure,
      computedBy: {
        sheetId: this.env.model.getters.getActiveSheetId(),
        formula: formula[0] === "=" ? formula : "=" + formula,
      },
    });
  }

  updateAggregator(aggregator: string) {
    this.props.onMeasureUpdated({
      ...this.props.measure,
      aggregator,
      id: this.props.generateMeasureId(this.props.measure.fieldName, aggregator),
    });
  }

  updateName(measure: PivotMeasure, userDefinedName?: string) {
    if (this.props.measure.computedBy && userDefinedName) {
      this.props.onMeasureUpdated({
        ...this.props.measure,
        userDefinedName,
        id: this.props.generateMeasureId(userDefinedName, this.props.measure.aggregator),
        fieldName: userDefinedName,
      });
    } else {
      this.props.onMeasureUpdated({
        ...this.props.measure,
        userDefinedName,
      });
    }
  }

  toggleMeasureVisibility() {
    this.props.onMeasureUpdated({
      ...this.props.measure,
      isHidden: !this.props.measure.isHidden,
    });
  }

  openShowValuesAs() {
    this.env.replaceSidePanel("PivotMeasureDisplayPanel", `pivot_key_${this.props.pivotId}`, {
      pivotId: this.props.pivotId,
      measure: this.props.measure,
    });
  }

  getColoredSymbolToken(token: Token): Color | undefined {
    if (token.type !== "SYMBOL") {
      return undefined;
    }
    const tokenValue = unquote(token.value, "'");
    if (
      this.props.definition.columns.some((col) => col.nameWithGranularity === tokenValue) ||
      this.props.definition.rows.some((row) => row.nameWithGranularity === tokenValue) ||
      this.props.definition.measures.some(
        (measure) => measure.id === tokenValue && measure.id !== this.props.measure.id
      )
    ) {
      return PIVOT_TOKEN_COLOR;
    }
    return undefined;
  }

  get isCalculatedMeasureInvalid(): boolean {
    return CompiledFormula.IsBadExpression(this.props.measure.computedBy?.formula ?? "");
  }

  get aggregatorOptions(): ValueAndLabel[] {
    const aggregators = this.props.aggregators[this.props.measure.type];
    const options = Object.keys(aggregators).map((key) => ({
      value: key,
      label: aggregators[key],
    }));
    if (this.props.measure.computedBy) {
      return [...options, { value: "", label: _t("Compute from totals") }];
    }
    return options;
  }

  getMeasureDescription(measure: PivotMeasure) {
    const measureDisplay = measure.display;
    if (!measureDisplay || measureDisplay.type === "no_calculations") {
      return "";
    }
    const pivot = this.env.model.getters.getPivot(this.props.pivotId);
    const field = [...pivot.definition.columns, ...pivot.definition.rows].find(
      (f) => f.nameWithGranularity === measureDisplay.fieldNameWithGranularity
    );
    const fieldName = field ? getFieldDisplayName(field) : "";
    const value = measureDisplay.value?.toString() || "";
    return measureDisplayTerms.descriptions[measureDisplay.type](fieldName, value);
  }
}
