import {
	isAnyTable,
	isTableType,
} from "qrc:/js/lib/generated/typeguard";
import {
	changeArticleUserData,
	changeNodesUserData,
	clearGraph as clearGraphImpl,
	createExternalNode as createExternalNodeImpl,
	redo as redoImpl,
	undo as undoImpl,
} from "qrc:/js/lib/graph_manipulator";
import {
	nodeIdKeyToVertex,
	projectName as projectNameImpl,
} from "qrc:/js/lib/graph_utils";
import {
	resetInternalTables as resetInternalTablesImpl,
	setInternalTables as setInternalTablesImpl,
} from "qrc:/js/lib/table_utils";
import {
	assert,
	isArray,
	isString,
	parseJsonDefault,
} from "qrc:/js/lib/utils";
import {
	computeGraphRepresentation as computeGraphRepresentationImpl,
} from "qrc:/js/src/gui_graph_representation";
import {
	editBendFlangeSafetyDistance as editBendFlangeSafetyDistanceImpl,
	editCsvLocale as editCsvLocaleImpl,
	editCompletionTimeMode as editCompletionTimeModeImpl,
	editDatabaseNestorSettings as editDatabaseNestorSettingsImpl,
	editDieBendingCalcConfig as editDieBendingCalcConfigImpl,
	editErpInterfaceVersion as editErpInterfaceVersionImpl,
	editFixedRotationSettings as editFixedRotationSettingsImpl,
	editGraphRepResourcesConfig as editGraphRepResourcesConfigImpl,
	editLaserSheetCuttingMovementParameters as editLaserSheetCuttingMovementParametersImpl,
	editLocalNestorSettings as editLocalNestorSettingsImpl,
	editManualMechanicalDeburringParameters as editManualMechanicalDeburringParametersImpl,
	editSheetScrapAreaThreshold as editSheetScrapAreaThresholdImpl,
	editTestReportSettings as editTestReportSettingsImpl,
	editTubeCuttingConfiguration as editTubeCuttingConfigurationImpl,
	processDialogInit as processDialogInitImpl,
	sheetTablesDialogInit as sheetTablesDialogInitImpl,
	tubeTablesDialogInit as tubeTablesDialogInitImpl,
	userTableEditorDialogInit as userTableEditorDialogInitImpl,
	IntAndExtTables,
	ProcessDialogInitData,
} from "qrc:/js/src/gui_internal";
import {
	openFiles as openFilesImpl,
	saveFile as saveFileImpl,
	FileHandlingResult,
} from "qrc:/js/src/gui_io_filesystem";
import {
	createUpdatedArticleUserData,
} from "qrc:/js/lib/article_userdata_config";
import {
	createUpdatedNodeUserData,
} from "qrc:/js/lib/userdata_utils";

export function openFiles(filesJson: unknown) : FileHandlingResult {
	if (!isString(filesJson)) {
		return wsi4.throwError("Expecting array of file paths");
	}
	const paths = parseJsonDefault(filesJson, [], (arg: unknown): arg is string[] => isArray(arg, isString));
	return openFilesImpl(paths);
}

export function saveFile(path: unknown) : FileHandlingResult {
	if (!isString(path)) {
		return wsi4.throwError("Expecting save file path");
	}
	return saveFileImpl(path);
}

export function changeArticleComment(nodeIdKey: unknown, comment: unknown): void {
	assert(isString(comment), "comment is expected to be of type string");
	const vertex = nodeIdKeyToVertex(nodeIdKey);
	const userData = createUpdatedArticleUserData("comment", comment, wsi4.node.articleUserData(vertex));
	changeArticleUserData([
		{
			vertex: vertex,
			userData: userData,
		},
	]);
}

export function changeNodeComment(nodeIdKey: unknown, comment: unknown): void {
	assert(isString(comment), "comment is expected to be of type string");
	const vertex = nodeIdKeyToVertex(nodeIdKey);
	const userData = createUpdatedNodeUserData("comment", vertex, comment);
	changeNodesUserData([
		{
			vertex: vertex,
			userData: userData,
		},
	]);
}

export function changeArticleDenominations(
	nodeIdKey: unknown,
	name: unknown,
	externalPartNumber: unknown,
	externalDrawingNumber: unknown,
	externalRevisionNumber: unknown,
) : void {
	assert(isString(name), "name is expected to be of type string");
	assert(isString(externalPartNumber), "externalPartNumber is expected to be of type string");
	assert(isString(externalDrawingNumber), "externalDrawingNumber is expected to be of type string");
	assert(isString(externalRevisionNumber), "externalRevisionNumber is expected to be of type string");
	const vertex = nodeIdKeyToVertex(nodeIdKey);

	let userData = wsi4.node.articleUserData(vertex);
	userData = createUpdatedArticleUserData("name", name, userData);
	userData = createUpdatedArticleUserData("externalPartNumber", externalPartNumber, userData);
	userData = createUpdatedArticleUserData("externalDrawingNumber", externalDrawingNumber, userData);
	userData = createUpdatedArticleUserData("externalRevisionNumber", externalRevisionNumber, userData);

	changeArticleUserData([
		{
			vertex: vertex,
			userData: userData,
		},
	]);
}

export function clearGraph() : void {
	return clearGraphImpl();
}

export function createExternalNode() : Vertex | undefined {
	return createExternalNodeImpl();
}

export function undo() : boolean {
	return undoImpl();
}

export function redo() : boolean {
	return redoImpl();
}

export function processDialogInit() : ProcessDialogInitData {
	return processDialogInitImpl();
}

export function userTableEditorDialogInit() : IntAndExtTables {
	return userTableEditorDialogInitImpl();
}

export function projectName() : string {
	return projectNameImpl();
}

export function resetInternalTables(tableTypes: unknown): void {
	if (!isArray(tableTypes, isTableType)) {
		return wsi4.throwError("Expecting array of TableType:s");
	}
	resetInternalTablesImpl(tableTypes);
	wsi4.tables.commit();
}

export function setInternalTables(tables: unknown): void {
	if (!isArray(tables, isAnyTable)) {
		return wsi4.throwError("Expecting array of AnyTable:s");
	}
	setInternalTablesImpl(tables);
	wsi4.tables.commit();
}

export function computeGraphRepresentation(knownNodeIds: unknown) : void {
	if (!Array.isArray(knownNodeIds)) {
		return wsi4.throwError("Expecting string");
	}
	return computeGraphRepresentationImpl(knownNodeIds);
}

export function editTestReportSettings() : void {
	return editTestReportSettingsImpl();
}

export function editTubeCuttingConfiguration() : void {
	return editTubeCuttingConfigurationImpl();
}

export function editFixedRotationSettings() : void {
	return editFixedRotationSettingsImpl();
}

export function editLaserSheetCuttingMovementParameters() : void {
	return editLaserSheetCuttingMovementParametersImpl();
}

export function editManualMechanicalDeburringParameters() : void {
	return editManualMechanicalDeburringParametersImpl();
}

export function editBendFlangeSafetyDistance() : void {
	return editBendFlangeSafetyDistanceImpl();
}

export function editCsvLocale() : void {
	return editCsvLocaleImpl();
}

export function editDatabaseNestorSettings() : void {
	return editDatabaseNestorSettingsImpl();
}

export function editDieBendingCalcConfig() : void {
	return editDieBendingCalcConfigImpl();
}

export function editLocalNestorSettings() : void {
	return editLocalNestorSettingsImpl();
}

export function tubeTablesDialogInit() : PrivateTubeTablesEditorInitData {
	return tubeTablesDialogInitImpl();
}

export function sheetTablesDialogInit() : PrivateSheetTablesEditorInitData {
	return sheetTablesDialogInitImpl();
}

export function editGraphRepResourcesConfig() : void {
	return editGraphRepResourcesConfigImpl();
}

export function editErpInterfaceVersion() : void {
	return editErpInterfaceVersionImpl();
}

export function editSheetScrapAreaThreshold(): void {
	editSheetScrapAreaThresholdImpl();
}

export function editCompletionTimeMode(): void {
	editCompletionTimeModeImpl();
}
