import {
	assert,
} from "./utils";

interface BulkEditorColumnBase {
	key: string;
	name: string;
	isOptional: boolean;
}

export interface BulkEditorLineEditColumn extends BulkEditorColumnBase {
	type: "lineEdit";
	initialValues: (string | undefined)[];
}

export interface BulkEditorTextEditColumn extends BulkEditorColumnBase {
	type: "textEdit";
	initialValues: (string | undefined)[];
}

export interface BulkEditorLabelColumn extends BulkEditorColumnBase {
	type: "label";
	initialValues: (string | undefined)[];
}

export interface BulkEditorCheckBoxColumn extends BulkEditorColumnBase {
	type: "checkBox";
	initialValues: (boolean | undefined)[];
}

export interface BulkEditorSpinBoxColumn extends BulkEditorColumnBase {
	type: "spinBox";
	min: number;
	max: number;
	decimals: number;
	initialValues: (number | undefined)[];
}

export interface BulkEditorDropDownColumn extends BulkEditorColumnBase {
	type: "dropDown";
	items: BulkEditorDropDownItem[];
	initialValues: (string | undefined)[];
}

export type BulkEditorColumn = BulkEditorLineEditColumn
| BulkEditorTextEditColumn
| BulkEditorCheckBoxColumn
| BulkEditorSpinBoxColumn
| BulkEditorDropDownColumn
| BulkEditorLabelColumn
;

export function bulkEditorDropDownColumn<T>(args: {
	key: string,
	name: string,
	values: T[],
	toId: (t: T) => string,
	toName: (t: T) => string,
	initialValues: (string | undefined)[],
	isOptional: boolean,
}): BulkEditorDropDownColumn {
	return {
		type: "dropDown",
		key: args.key,
		name: args.name,
		isOptional: args.isOptional,
		items: args.values.map(v => ({
			id: args.toId(v),
			name: args.toName(v),
		})),
		initialValues: args.initialValues,
	};
}

function createCellConfig(column: BulkEditorColumn, rowIndex: number): BulkEditorCellConfig {
	switch (column.type) {
		case "label": {
			const result: BulkEditorCellConfig = {
				type: column.type,
				content: {},
			};
			const initialValue = column.initialValues[rowIndex];
			if (initialValue !== undefined) {
				result.content.initialValue = initialValue;
			}
			return result;
		}
		case "lineEdit":
		case "textEdit": {
			const result: BulkEditorCellConfig = {
				type: column.type,
				content: {
					isOptional: column.isOptional,
				},
			};
			const initialValue = column.initialValues[rowIndex];
			if (initialValue !== undefined) {
				result.content.initialValue = initialValue;
			}
			return result;
		}
		case "checkBox": {
			const result: BulkEditorCellConfig = {
				type: column.type,
				content: {
					isOptional: column.isOptional,
				},
			};
			const initialValue = column.initialValues[rowIndex];
			if (initialValue !== undefined) {
				result.content.initialValue = initialValue;
			}
			return result;
		}
		case "spinBox": {
			const result: BulkEditorCellConfig = {
				type: column.type,
				content: {
					isOptional: column.isOptional,
					min: column.min,
					max: column.max,
					decimals: column.decimals,
				},
			};
			const initialValue = column.initialValues[rowIndex];
			if (initialValue !== undefined) {
				result.content.initialValue = initialValue;
			}
			return result;
		}
		case "dropDown": {
			const result: BulkEditorCellConfig = {
				type: column.type,
				content: {
					isOptional: column.isOptional,
					items: column.items,
				},
			};
			const initialValue = column.initialValues[rowIndex];
			if (initialValue !== undefined) {
				result.content.initialValue = initialValue;
			}
			return result;
		}
	}
}

/**
 * Convenience function for the "simple" case that all cells of a column have the same configuration.
 * (I.e. cell configs can only differ by the initial values.)
 */
export function showSimpleBulkEditor(columns: BulkEditorColumn[], widgetState?: string): WidgetResultBulkEditor {
	const columnConfigs: BulkEditorColumnConfig[] = columns.map(column => ({
		key: column.key,
		name: column.name,
	}));

	if (columns.length > 0 && (columns.some(column => column.initialValues.length !== columns[0]!.initialValues.length)
					|| columns.some((column, index) => index !== 0 && column.key === columns[0]!.key))) {
		return wsi4.throwError("Bulk editor config inconsistent");
	}

	const rowConfigs: BulkEditorCellConfig[][] = [];
	if (columns.length > 0) {
		columns[0]!.initialValues.forEach(_ => rowConfigs.push([]));
	}

	columns.forEach(column => {
		column.initialValues.forEach((_, index) => {
			rowConfigs[index]!.push(createCellConfig(column, index));
		});
	});

	const widgetConfig: WidgetConfig = {
		type: "bulkEditor",
		content: {
			columnConfigs: columnConfigs,
			rowConfigs: rowConfigs,
		},
	};
	if (widgetState !== undefined) {
		widgetConfig.content.widgetState = widgetState;
	}

	const dialogResult = wsi4.ui.show(widgetConfig);
	assert(dialogResult !== undefined, "Always expecting valid result from bulk editor");
	assert(dialogResult.type === "bulkEditor", "Widget result inconsistent");
	return dialogResult.content;
}
