import { CompiledFormula } from "../formulas/compiler";
import { Format, FormattedValue } from "./format";
import { CellPosition, FunctionResultObject, Link, Style } from "./misc";

interface CellAttributes {
  readonly id: number;
  readonly style?: Style;
  readonly format?: Format;
}

export interface LiteralCell extends CellAttributes {
  /**
   * Raw cell content
   */
  readonly content: string;
  readonly isFormula: false;
  readonly parsedValue: CellValue;
}

export interface FormulaCell extends CellAttributes {
  readonly isFormula: true;
  readonly compiledFormula: CompiledFormula;
}

export type Cell = LiteralCell | FormulaCell;

interface EvaluatedCellProperties extends FunctionResultObject {
  readonly format?: Format;
  /**
   * Cell value formatted based on the format
   */
  readonly formattedValue: FormattedValue;
  readonly defaultAlign: "right" | "center" | "left";
  /**
   * Can the cell appear in an automatic sum zone.
   */
  readonly isAutoSummable: boolean;
  readonly link?: Link;
  readonly position?: CellPosition;
}

export type CellValue = string | number | boolean | null; // We use null to represent an empty cell. This choice is preferred over using undefined because when passing values to a JavaScript function, undefined may be replaced by a default value.

export type EvaluatedCell = NumberCell | TextCell | BooleanCell | EmptyCell | ErrorCell;

export interface NumberCell extends EvaluatedCellProperties {
  readonly type: CellValueType.number;
  readonly value: number;
}

export interface TextCell extends EvaluatedCellProperties {
  readonly type: CellValueType.text;
  readonly value: string;
}

export interface BooleanCell extends EvaluatedCellProperties {
  readonly type: CellValueType.boolean;
  readonly value: boolean;
}

export interface EmptyCell extends EvaluatedCellProperties {
  readonly type: CellValueType.empty;
  readonly value: null;
}

export interface ErrorCell extends EvaluatedCellProperties {
  readonly type: CellValueType.error;
  readonly value: string;
  readonly message?: string;
}

export enum CellValueType {
  boolean = "boolean",
  number = "number",
  text = "text",
  empty = "empty",
  error = "error",
}
