import { PdfiumPageP__Output } from "../../generated_proto/ironpdfengineproto/PdfiumPageP";
import { PageInfo, PageRotation } from "../../../public/page";
import {
	PdfiumPageRotationP,
	PdfiumPageRotationP__Output,
} from "../../generated_proto/ironpdfengineproto/PdfiumPageRotationP";
import { PdfPermission } from "../../../public/security";
import { PdfiumPdfDocumentPermissionsP__Output } from "../../generated_proto/ironpdfengineproto/PdfiumPdfDocumentPermissionsP";
import {
	StringDictionaryP,
	StringDictionaryP__Output,
} from "../../generated_proto/ironpdfengineproto/StringDictionaryP";

export function PageInfoFromProto(proto: PdfiumPageP__Output): PageInfo {
	return {
		pageRotation: PageRotationFromProto(proto?.pageRotation) ?? 0,
		millimeterHeight: proto.height ?? 0,
		millimeterWidth: proto.width ?? 0,
		printerPointHeight: proto.printHeight ?? 0,
		printerPointWidth: proto.printWidth ?? 0,
	};
}

export function PageRotationFromProto(
	proto?: PdfiumPageRotationP__Output
): PageRotation {
	switch (proto?.enumValue) {
		case 0:
			return 0;
		case 1:
			return 90;
		case 2:
			return 180;
		case 3:
			return 270;
		default:
			return 0;
	}
}

export function PageRotationToProto(value?: PageRotation): PdfiumPageRotationP {
	switch (value) {
		case 0:
			return { enumValue: 0 };
		case 90:
			return { enumValue: 1 };
		case 180:
			return { enumValue: 2 };
		case 270:
			return { enumValue: 3 };
		default:
			return { enumValue: 4 };
	}
}

enum PdfDocumentPermissionsEnum {
	None = -3904,
	AllowAccessibilityExtractContent = 0b1000000000,
	AllowAnnotations = 0b100000,
	AllowAssembleDocument = 0b10000000000,
	AllowExtractContent = 0b10000,
	AllowFillForms = 0b100000000,
	AllowPrintFullQuality = 0b100000000000,
	AllowModify = 0b1000,
	AllowPrint = 0b100,
	AllowAll = -4,
}

export function pdfPermissionFromProto(
	pdfPermissionP: PdfiumPdfDocumentPermissionsP__Output
): PdfPermission {
	const permissionsEnum: PdfDocumentPermissionsEnum =
		pdfPermissionP.enumValue == undefined
			? PdfDocumentPermissionsEnum.None
			: pdfPermissionP.enumValue;
	return convertPermissionsEnumToInterface(permissionsEnum);
}

export function StringDictionaryFromProto(
	stringDictionaryP: StringDictionaryP__Output | undefined
): Map<string, string> {
	if (stringDictionaryP?.items) {
		return new Map(
			stringDictionaryP.items
				.filter((x) => x.key !== undefined && x.value !== undefined)
				// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
				.map((x) => [x.key!, x.value!])
		);
	}
	return new Map<string, string>();
}

export function StringDictionaryToProto(
	map: Map<string, string>
): StringDictionaryP {
	return {
		items: Array.from(map).map(([key, value]) => ({
			key,
			value,
		})),
	};
}

export function convertPermissionsEnumToInterface(
	inputEnum: PdfDocumentPermissionsEnum
): PdfPermission {
	const interfaceObject: PdfPermission = {};
	const enumKeys = Object.keys(PdfDocumentPermissionsEnum);

	for (const key of enumKeys) {
		if (!isNaN(Number(key))) {
			const enumKey =
				PdfDocumentPermissionsEnum[
					key as keyof typeof PdfDocumentPermissionsEnum
				];
			interfaceObject[enumKey as unknown as keyof PdfPermission] =
				(inputEnum &
					PdfDocumentPermissionsEnum[
						enumKey as unknown as keyof typeof PdfDocumentPermissionsEnum
					]) !==
				0;
		}
	}
	return interfaceObject;
}

export function convertPermissionsInterfaceToEnum(
	inputInterface: PdfPermission
): PdfDocumentPermissionsEnum {
	let enumObject: PdfDocumentPermissionsEnum =
		PdfDocumentPermissionsEnum.AllowAll;

	for (const key in PdfDocumentPermissionsEnum) {
		const enumValue = PdfDocumentPermissionsEnum[key as any];
		if (typeof enumValue === "number") {
			if (inputInterface[key as keyof PdfPermission] === false) {
				enumObject =
					enumObject & ~enumValue; // Remove this permission
			}
		}
	}
	return enumObject;
}
