import { Resource } from "../src/ResourceModels";
import { EleventyCollectionItem } from "../src/models";
import { POSSIBLE_RESOURCE_TYPES, RESOURCE_TYPES } from "../src/resourceType";
import { ResourceMapType } from "./config";

export type RESOURCE_MODELS_BY_TYPE<
	RESOURCE extends RESOURCE_TYPES | POSSIBLE_RESOURCE_TYPES =
		| RESOURCE_TYPES
		| POSSIBLE_RESOURCE_TYPES
> = RESOURCE extends keyof ResourceMapType
	? Array<ResourceMapType[RESOURCE]>
	: RESOURCE extends Array<RESOURCE_TYPES>
	? // @ts-ignore
	  Array<ResourceMapType[RESOURCE[number]]>
	: Resource[];

export type RESOURCE_MODEL_BY_TYPE<
	T extends RESOURCE_TYPES | POSSIBLE_RESOURCE_TYPES
> = T extends keyof ResourceMapType
	? ResourceMapType[T]
	: T extends Array<RESOURCE_TYPES>
	? // @ts-ignore
	  ResourceMapType[T[number]]
	: Resource;

export type QueryFilter<
	T extends RESOURCE_TYPES | POSSIBLE_RESOURCE_TYPES =
		| RESOURCE_TYPES
		| POSSIBLE_RESOURCE_TYPES
> = {
	channel?: string;
	limit?: number;
	resourceTypes?: T;
	tag?: string;
	customFilter?: (resource: RESOURCE_MODEL_BY_TYPE<T>) => boolean;
	sorter?: (
		a: RESOURCE_MODEL_BY_TYPE<T>,
		b: RESOURCE_MODEL_BY_TYPE<T>
	) => number;
};

export function getResources<
	T extends RESOURCE_TYPES | POSSIBLE_RESOURCE_TYPES
>(
	allResourcesList: Resource[],
	filter: QueryFilter<T>
): RESOURCE_MODELS_BY_TYPE<T> | null {
	let resources = allResourcesList;
	const types =
		filter && filter.resourceTypes != null
			? Array.isArray(filter.resourceTypes)
				? [...filter.resourceTypes]
				: [filter.resourceTypes]
			: undefined;
	if (types) {
		resources = resources.filter((r) => types.includes(r.resourceType!));
	}

	const tag = filter && filter.tag;
	if (tag) {
		resources = resources.filter((r) => r.tags?.includes(tag));
	}

	const channel = filter && filter.channel;
	if (channel) {
		resources = resources.filter((r) => r.channel == channel);
	}

	const customFilter = filter && filter.customFilter;
	if (customFilter) {
		resources = resources.filter((x) =>
			customFilter(x as RESOURCE_MODEL_BY_TYPE<T>)
		);
	}

	if (resources.length == 0) {
		return null;
	}

	const sorter = filter && filter.sorter;
	if (sorter) {
		// Sort by custom sorter
		resources.sort((a, b) =>
			sorter(a as RESOURCE_MODEL_BY_TYPE<T>, b as RESOURCE_MODEL_BY_TYPE<T>)
		);
	} else {
		// Sort in reverse date order
		resources.sort((a, b) => b.date.getTime() - a.date.getTime());
	}

	const limit = filter && filter.limit;
	if (limit) {
		resources = resources.slice(0, limit);
	}

	return resources as RESOURCE_MODELS_BY_TYPE<T>;
}

// TODO PWE Get rid of this and just use collections.resourceMap
export function getResource(resources: Resource[], url: string): Resource {
	return resources.filter((r) => r.url == url)[0];
}

export function sortByFrontmatter(
	items: EleventyCollectionItem[],
	sortByOption?: string
) {
	if (!sortByOption) {
		return;
	}

	let sortOrder = 1;
	if (sortByOption[0] === "-") {
		sortOrder = -1;
		sortByOption = sortByOption.substring(1);
	}

	switch (sortByOption) {
		case "title":
			items.sort((a, b) => {
				const aTitle = a.data.title.toLowerCase();
				const bTitle = b.data.title.toLowerCase();
				return (aTitle > bTitle ? -1 : bTitle > aTitle ? 1 : 0) * sortOrder;
			});
			break;
		case "date":
			items.sort((a, b) => {
				let result = a.page.date.getTime() - b.page.date.getTime();
				return result * sortOrder;
			});
			break;
		default:
			break;
	}
}
