import { IExecuteFunctions } from 'n8n-core';
import {
	IDataObject,
	ILoadOptionsFunctions,
	INodeExecutionData,
	INodePropertyOptions,
	INodeType,
	INodeTypeDescription,
} from 'n8n-workflow';
import {
	collectionFields,
	collectionOperations,
} from './CollectionDescription';
import {
	createCollectionEntry,
	getAllCollectionEntries,
	getAllCollectionNames,
} from './CollectionFunctions';
import {
	formFields,
	formOperations
} from './FormDescription';
import { submitForm } from './FormFunctions';
import {
	singletonFields,
	singletonOperations,
} from './SingletonDescription';
import {
	getAllSingleton,
	getAllSingletonNames,
} from './SingletonFunctions';

export class Cockpit implements INodeType {
	description: INodeTypeDescription = {
		displayName: 'Cockpit',
		name: 'cockpit',
		icon: 'file:cockpit.png',
		group: ['output'],
		version: 1,
		subtitle: '={{ $parameter["operation"] + ": " + $parameter["resource"] }}',
		description: 'Consume Cockpit API',
		defaults: {
			name: 'Cockpit',
			color: '#000000',
		},
		inputs: ['main'],
		outputs: ['main'],
		credentials: [
			{
				name: 'cockpitApi',
				required: true,
			},
		],
		properties: [
			{
				displayName: 'Resource',
				name: 'resource',
				type: 'options',
				default: 'collections',
				description: 'Resource to consume.',
				options: [
					{
						name: 'Collection',
						value: 'collections',
					},
					{
						name: 'Form',
						value: 'forms',
					},
					{
						name: 'Singleton',
						value: 'singletons',
					},
				],
			},


			...collectionOperations,
			...collectionFields,
			...formOperations,
			...formFields,
			...singletonOperations,
			...singletonFields,
		],
	};


	methods = {
		loadOptions: {
			async getCollections(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
				const collections = await getAllCollectionNames.call(this);

				return collections.map(itemName => {
					return {
						name: itemName,
						value: itemName,
					}
				});
			},

			async getSingletons(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
				const singletons = await getAllSingletonNames.call(this);

				return singletons.map(itemName => {
					return {
						name: itemName,
						value: itemName,
					}
				});
			},
		},
	};

	async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
		const items = this.getInputData();
		const returnData: IDataObject[] = [];
		const length = items.length as unknown as number;
		const resource = this.getNodeParameter('resource', 0) as string;
		const operation = this.getNodeParameter('operation', 0) as string;

		let responseData;

		for (let i = 0; i < length; i++) {
			if (resource === 'collections') {
				const collectionName = this.getNodeParameter('collection', i) as string;
				if (operation === 'create') {
					const data = this.getNodeParameter('data', i) as IDataObject;

					responseData = await createCollectionEntry.call(this, collectionName, data);
				} else if (operation === 'getAll') {
					const options = this.getNodeParameter('options', i) as IDataObject;

					responseData = await getAllCollectionEntries.call(this, collectionName, options);
				} else if (operation === 'update') {
					const id = this.getNodeParameter('id', i) as string;
					const data = this.getNodeParameter('data', i) as IDataObject;

					responseData = await createCollectionEntry.call(this, collectionName, data, id);
				}
			} else if (resource === 'forms') {
				const formName = this.getNodeParameter('form', i) as string;
				if (operation === 'submit') {
					const form = this.getNodeParameter('form', i) as IDataObject;

					responseData = await submitForm.call(this, formName, form);
				}
			} else if (resource === 'singletons') {
				const singletonName = this.getNodeParameter('singleton', i) as string;
				if (operation === 'getAll') {
					responseData = await getAllSingleton.call(this, singletonName);
				}
			}

			if (Array.isArray(responseData)) {
				returnData.push.apply(returnData, responseData as IDataObject[]);
			} else {
				returnData.push(responseData as IDataObject);
			}
		}

		return [this.helpers.returnJsonArray(returnData)];
	}
}
