import type { ModelOfType, ModelTypes } from "../interfaces/common.js";
import type { SupportedLayer } from "../../interfaces.js";
import type { IFeatureLayer } from "../../spec/rest-js-types.js";
import type { ChartConfig } from "../../utils/types/index.js";

/**
 * Creates a new chart model for config interaction based on the provided properties.
 * Various combinations of properties `layer`, `iLayer`, `chartType`, and `config` are supported.
 *
 * @param props - The properties used to set up the chart.
 * @example
 * ```ts
 * const chartModel = await createModel({
 *  layer: myLayer,
 *  chartType: "gauge",
 * });
 * ```
 */
export function createModel<T extends ModelTypes>(props: CreateModelProps<T>): Promise<ModelOfType<T>>;

/**
 * Properties used by the `createModel` function to create a new model.
 * Various combinations of `layer`, `iLayer`, `chartType`, and `config` are supported.
 */
export type CreateModelProps<T extends ModelTypes> = ILayerAndSourcelessConfig<T> | ILayerAndType<T> | LayerAndSourcelessConfig<T> | LayerAndType<T> | SourcedConfig<T>;

/**
 * Properties used by the `createModel` function to create a new model based on the provided `layer` and `chartType`.
 *
 * A new model of the specified type will be created using default values.
 */
export type LayerAndType<T extends ModelTypes> = {
  layer: SupportedLayer;
  chartType: T;
};

/**
 * Properties used by the `createModel` function to create a new model based on the provided `iLayer` and `chartType`.
 *
 * A new model of the specified type will be created using default values.
 */
export type ILayerAndType<T extends ModelTypes> = {
  iLayer: IFeatureLayer;
  chartType: T;
};

/**
 * Properties used by the `createModel` function to create a new model based on the provided `iLayer` and `config`.
 *
 * The `config` is considered "sourceless" since its `iLayer` property is not required.
 */
export type LayerAndSourcelessConfig<T extends ModelTypes> = {
  layer: SupportedLayer;
  config: ChartConfig<T>;
};

/**
 * Properties used by the `createModel` function to create a new model based on the provided `iLayer` and `config`.
 *
 * The `config` is considered "sourceless" since its `iLayer` property is not required.
 */
export type ILayerAndSourcelessConfig<T extends ModelTypes> = {
  iLayer: IFeatureLayer;
  config: ChartConfig<T>;
};

/**
 * Properties used by the `createModel` function to create a new model based on the provided `config`.
 *
 * **Note: The `config` must have its `iLayer` property (source) defined.**
 */
export type SourcedConfig<T extends ModelTypes> = {
  config: ChartConfig<T>;
};