import { BackgroundColorsTokenType } from './design-token.type';
import { AxisDomain, AxisScale } from '../polyfill/d3/d3-axis-polyfill';
import { D3SelectionPolyfill } from '../polyfill/d3/d3-selection-polyfill';

export type { AxisDomain, AxisScale, Axis } from '../polyfill/d3/d3-axis-polyfill';
export type Selection<
	GElement extends Element,
	Datum,
	PElement extends Element,
	PDatum,
> = D3SelectionPolyfill<GElement, Datum, PElement, PDatum>;

/**
 * Rendering mode for charts: SVG or Canvas.
 */
export type ChartGraphMode = 'svg' | 'canvas';

/**
 * Layout dimensions configuration for a chart.
 */
export type ChartLayout = {
	/**
	 * Width of the chart (pixel value or CSS string).
	 */
	width?: number | string;
	/**
	 * Height of the chart (pixel value or CSS string).
	 */
	height?: number | string;
	/**
	 * Margin spacing around chart content.
	 */
	margin?: ChartLayoutMargin;
};

/**
 * Margin settings within a chart layout.
 */
export type ChartLayoutMargin = {
	/**
	 * Top margin in pixels.
	 */
	top?: number;
	/**
	 * Right margin in pixels.
	 */
	right?: number;
	/**
	 * Bottom margin in pixels.
	 */
	bottom?: number;
	/**
	 * Left margin in pixels.
	 */
	left?: number;
};

/**
 * Callbacks for interactive chart behaviors.
 */
export type InteractOption = {
	/**
	 * Callback invoked when pointer moves over chart.
	 */
	onMove?: () => void;
	/**
	 * Callback invoked when chart is clicked.
	 */
	onClick?: () => void;
	/**
	 * Callback invoked when pointer hovers over chart.
	 */
	onHover?: () => void;
};

/**
 * Event types recognized by chart interaction handlers.
 */
export type EventType = 'click' | 'mouseover';

/**
 * Describes an entry used to determine and handle chart events.
 */
export type InteractingEntry = {
	/**
	 * Type of event to listen for (click or mouseover).
	 */
	eventType: EventType;
	/**
	 * Function to determine if event should be handled.
	 */
	shouldHandle: (event: Event) => boolean;
	/**
	 * Function to handle the event if shouldHandle returns true.
	 */
	handle: (event: Event) => void;
};

/**
 * Options passed to a chart drawer implementation.
 */
export type ChartDrawerOptions<T> = {
	/**
	 * Rendering-specific options for the chart drawer.
	 */
	renderOptions: T;
};

/**
 * Types of data representation for the x-axis.
 */
export type ChartXAxisType = 'value' | 'time' | 'category';

/**
 * Formatter function invoked for axis tick labels.
 */
export type LabelFormatterType<T> = (tick: T) => string;

export type ChartOptions<T> = {
	/**
	 * DOM element to render the chart into.
	 */
	container: HTMLElement;
	/**
	 * Specifies the chart layout.
	 */
	layout?: ChartLayout;
	/**
	 * Chart rendering mode (SVG or Canvas).
	 */
	mode?: ChartGraphMode;
	/**
	 * Defines the colors used in the chart.
	 */
	colors?: BackgroundColorsTokenType[];
	/**
	 * Required if displaying legends in the chart.
	 */
	legends?: string[];
	/**
	 * Configures settings for the chart's x-axis.
	 */
	xAxis?: ChartOptionsXAxis;
	/**
	 * Configures settings for the chart's y-axis.
	 */
	yAxis?: ChartOptionsYAxis;
} & T;

/**
 * Configuration for the x-axis of a chart.
 */
export type ChartOptionsXAxis = {
	/**
	 * Type of x-axis (value, time, or category).
	 */
	type?: ChartXAxisType;
	/**
	 * Function to format tick labels on x-axis.
	 */
	labelFormatter?: LabelFormatterType<number | string | Date>;
	/**
	 * Function to sort x-axis categories.
	 */
	sorter?: (item: string, nextItem: string) => number;
};

/**
 * Configuration for the y-axis of a chart.
 */
export type ChartOptionsYAxis = {
	/**
	 * Function to format tick labels on y-axis.
	 */
	labelFormatter?: LabelFormatterType<number>;
};

/**
 * Describes extension information for chart axes or ranges.
 */
export type ChartExtend<T> = {
	/**
	 * Starting position of the extension range.
	 */
	start: ChartPosition;
	/**
	 * Ending position of the extension range.
	 */
	end: ChartPosition;
	/**
	 * Size of each tick mark on the axis.
	 */
	tickSize: number;
	/**
	 * Function to format tick labels.
	 */
	labelFormatter?: LabelFormatterType<number | string | Date>;
	/**
	 * Scale function or configuration for the axis.
	 */
	scale: T;
	/**
	 * Width of the axis area in pixels.
	 */
	width: number;
	/**
	 * Height of the axis area in pixels.
	 */
	height: number;
	/**
	 * Direction orientation (vertical or horizontal).
	 */
	direction?: directionType;
};

/**
 * Options for drawing a line between two positions.
 */
export type ChartLineOptions = {
	/**
	 * Starting position for the line.
	 */
	from: ChartPosition;
	/**
	 * Ending position for the line.
	 */
	to: ChartPosition;
};

/**
 * Rectangle plotting options, used by bar/area charts.
 */
export type ChartRectOptions = {
	/**
	 * Data source array for rendering rectangles.
	 */
	dataSource?: unknown[];
	/**
	 * D3 scale function for x-axis positioning.
	 */
	xScale: AxisScale<AxisDomain>;
	/**
	 * D3 scale function for y-axis positioning.
	 */
	yScale: AxisScale<AxisDomain>;
	/**
	 * Color palette for rendering multiple series.
	 */
	colors?: BackgroundColorsTokenType[];
	/**
	 * Direction orientation (vertical or horizontal).
	 */
	direction?: directionType;
};

/**
 * Settings for rendering chart legends.
 */
export type ChartLegendOptions = {
	/**
	 * Position where legend should be rendered.
	 */
	position: ChartPosition;
	/**
	 * Array of individual legend items.
	 */
	legends: ChartLegendOptionsLegends[];
};

/**
 * Individual legend item configuration.
 */
export type ChartLegendOptionsLegends = {
	/**
	 * Data field name associated with this legend item.
	 */
	field: string;
	/**
	 * Color displayed for this legend item.
	 */
	color: string;
	/**
	 * Icon identifier for the legend item.
	 */
	icon: string;
};

/**
 * Options for drawing paths (lines) on a chart.
 */
export type ChartPathOptions = {
	/**
	 * Array of positions forming the path line(s). Can be single path or multiple series.
	 */
	positions: ChartPosition[] | ChartPosition[][];
	/**
	 * Color palette for rendering multiple path series.
	 */
	colors?: BackgroundColorsTokenType[];
};

/**
 * Generic data point with x/y values.
 */
export type ChartData<T> = {
	/**
	 * X-axis value (category, time, or number).
	 */
	x: T;
	/**
	 * Y-axis value (numeric).
	 */
	y: number;
};

/**
 * Data point where x is a string category.
 */
export type StringCategorizedChartData = ChartData<string>;

/**
 * Data point where x is a Date value.
 */
export type DateCategorizedChartData = ChartData<Date>;

/**
 * Numeric position data point.
 */
export type ChartPosition = ChartData<number>;

/**
 * Union type representing any supported chart data point.
 */
export type ChartDataSourceItem = ChartPosition | StringCategorizedChartData | DateCategorizedChartData;

/**
 * Data record used for pie/donut charts and similar.
 */
export type RecordChartData = {
	/**
	 * Name or label of the data record.
	 */
	name: string;
	/**
	 * Numeric value for the record (pie slice size, etc.).
	 */
	value: number;
	/**
	 * Optional custom label to display for this record.
	 */
	label?: string;
};

/**
 * Options for drawing arcs (pie/donut slices).
 */
export type ChartArcOptions = {
	/**
	 * Array of arc segment definitions.
	 */
	data: ArcPathItem[];
	/**
	 * Color palette for rendering arc segments.
	 */
	colors?: BackgroundColorsTokenType[];
	/**
	 * Inner radius for donut-shaped arcs.
	 */
	donutRadius: number;
	/**
	 * Outer radius of the arc circle.
	 */
	outerRadius: number;
	/**
	 * Center point of the arc circle.
	 */
	center: ChartPosition;
};

/**
 * Represents individual arc segment information.
 */
export type ArcPathItem = {
	/**
	 * The underlying data record for this arc segment.
	 */
	data: RecordChartData;
	/**
	 * Index position of this arc in the sequence.
	 */
	index: number;
	/**
	 * Numeric value determining arc angle.
	 */
	value: number;
	/**
	 * Starting angle of the arc in radians.
	 */
	startAngle: number;
	/**
	 * Ending angle of the arc in radians.
	 */
	endAngle: number;
	/**
	 * Padding angle between arc segments in radians.
	 */
	padAngle: number;
};

/**
 * SVG text-anchor options.
 */
export type TextAnchorType = 'start' | 'middle' | 'end';

/**
 * Direction orientation for charts.
 */
export type directionType = 'vertical' | 'horizontal';

/**
 * Input type for line chart data.
 */
export type LineChartDataType = {
	/**
	 * Array of data points or multiple series for line chart.
	 */
	dataSource: ChartDataSourceItem[] | ChartDataSourceItem[][];
	/**
	 * Direction orientation (vertical or horizontal).
	 */
	direction?: directionType;
};

/**
 * Input type for pie or donut chart sources.
 */
export type PieChartSourceType = {
	/**
	 * Array of data records for pie/donut chart.
	 */
	dataSource: RecordChartData[];
	/**
	 * Inner radius for donut style (0 for pie).
	 */
	donutRadius?: number;
	/**
	 * Chart type (Pie or Donut).
	 */
	type?: 'Pie' | 'Donut';
};
