import {
	DataSource,
	ExternalInputEntry,
} from "./external_input";
import {
	exhaustiveStringTuple,
} from "./utils";

function loadDataSource(dataSource: Readonly<DataSource>): ArrayBuffer | undefined {
	switch (dataSource.tag) {
		case "filePath": return wsi4.io.fs.readFile(dataSource.path);
		case "fileContent": {
			switch (dataSource.type) {
				case "plainText": return wsi4.util.stringToArrayBuffer(dataSource.data);
				case "base64": return wsi4.util.fromBase64(wsi4.util.stringToArrayBuffer(dataSource.data));
			}
		}
	}
}

export type TerminalArticleAttributes = Pick<ExternalInputEntry, "articleName">;

/**
 * Internal intermediate input representation
 */
export interface NormalizedInputEntry {
	data: ArrayBuffer;
	importId: string;
	multiplicity: number;
	sheetThickness: number | undefined;
	terminalArticleAttributes: TerminalArticleAttributes;
}

function extractTerminalArticleAttrs(entry: Readonly<ExternalInputEntry>): TerminalArticleAttributes {
	const attrs: TerminalArticleAttributes = {};
	exhaustiveStringTuple<keyof TerminalArticleAttributes>()(
		"articleName",
	).forEach(key => {
		if (entry[key] !== undefined) {
			// @ts-ignore
			attrs[key] = entry[key];
		}
	});
	return attrs;
}

/**
 * An invalid DataSource is considered an error.
 * (E.g. an invalid input file path.)
 *
 * A DataSource with invalid file *content* is *not* considered invalid.
 *
 * An invalid file path should not occur:
 * - When receiving paths from the GUI, invalid paths are not exected (e.g. from a file dialog).
 * - When receiving paths from a third party (e.g. an ERP) the submitted paths should be correct.
 */
export function loadExternalInputEntry(entry: Readonly<ExternalInputEntry>): NormalizedInputEntry {
	const buffer = loadDataSource(entry.dataSource);
	if (buffer === undefined) {
		wsi4.throwError(
			`Cannot read ExternalInputEntry of type ${entry.dataSource.tag}`
				+ (() => {
					switch (entry.dataSource.tag) {
						case "filePath": return ` (${entry.dataSource.path})`;
						case "fileContent": return ` (${entry.dataSource.type})`;
					}
				})());
	}
	return {
		data: buffer,
		importId: entry.importId ?? wsi4.util.createUuid(),
		multiplicity: entry.multiplicity ?? 1,
		sheetThickness: entry.sheetThickness,
		terminalArticleAttributes: extractTerminalArticleAttrs(entry),
	};
}

/**
 * An invalid input entry is considered an error.
 * (E.g. an invalid input file path.)
 */
export function loadExternalInput(externalInputEntries: readonly Readonly<ExternalInputEntry>[]): NormalizedInputEntry[] {
	return externalInputEntries.map(entry => loadExternalInputEntry(entry));
}
