import { ActionAPI } from '../../../ActionAPI';
import { EditorAPI, EditorAPI_Field } from '../../../EditorAPI';
import { StudioMonitor } from 'studiomonitor-api';

module.exports = (actionAPI: ActionAPI) => {
	//Handle the action when executed
	actionAPI.handle(
		(properties: Source_Properties, status: (text: string, type?: 'info' | 'error' | 'warn') => void) => {
			var connectionID = properties.connectionID != undefined ? properties.connectionID : 'none';
			var sourceID = properties.sourceID != undefined ? properties.sourceID : 'none';
			if (connectionID != 'none') {
				if (sourceID != 'none') {
					var connection = actionAPI.getConnection('studiomonitor', connectionID);

					if (connection.instance != undefined) {
						var monitor: StudioMonitor = connection.instance;
						monitor
							.setSource(sourceID)
							.then(() => {
								status('Source was set');
							})
							.catch((error) => {
								status(`Error whilst setting source: ${error.message}`, 'error');
							});
					}
				} else status('No source specified', 'error');
			} else status('No connection specified', 'error');
		}
	);

	//Handle the interactive editor
	actionAPI.onOpenEditor((editorAPI: EditorAPI, properties: Source_Properties) => {
		var connectionID = properties.connectionID != undefined ? properties.connectionID : 'none';
		var sourceID = properties.sourceID != undefined ? properties.sourceID : 'none';

		var monitor: StudioMonitor = null;
		var currentIP: string = null;
		var currentPort: number = null;

		var fields: EditorAPI_Field[] = [
			{
				id: 'connectionID',
				name: 'Connection',
				type: 'connection',
				value: connectionID,
				connectionType: 'studiomonitor'
			},
			{
				id: 'sourceID',
				name: 'Source',
				type: 'select',
				value: sourceID,
				values: []
			}
		];

		function updateAddress(connectionID: string, callback: (changed: boolean) => void) {
			if (connectionID != 'none') {
				var connection = actionAPI.getConnection('studiomonitor', connectionID);

				var ip: string = <string>connection.properties.ip;
				var port: number = <number>connection.properties.port;
				if (currentIP != ip || currentPort != port) {
					currentIP = ip;
					currentPort = port;
					monitor = connection.instance;
					callback(true);
				} else {
					callback(false);
				}
			} else {
				if (currentIP != null || currentPort != null) {
					currentIP = null;
					currentPort = null;
					monitor = null;
					callback(true);
				} else {
					callback(false);
				}
			}
		}

		function updateSources(callback: () => void) {
			if (monitor != null)
				monitor
					.getSources()
					.then((sources: string[]) => {
						fields[1].values = sources.map((source) => {
							return { id: source, text: source };
						});
						callback();
					})
					.catch((error) => {
						fields[1].values = [];
						callback();
					});
			else {
				fields[1].values = [];
				callback();
			}
		}

		function validate(fieldValues: Source_Properties) {
			fields[0].value = fieldValues.connectionID;
			fields[1].value = fieldValues.sourceID;

			editorAPI.saveProperties({ connectionID: fieldValues.connectionID, sourceID: fieldValues.sourceID });

			updateAddress(fieldValues.connectionID, (changed) => {
				if (changed) {
					updateSources(() => {
						editorAPI.setFields(fields);
					});
				} else editorAPI.setFields(fields);
			});
		}

		validate({ connectionID, sourceID });

		editorAPI.onFieldChanges((fields: EditorAPI_Field[]) => {
			var fieldValues: Source_Properties = <any>editorAPI.tools.objectifyFieldsValues(fields);

			validate(fieldValues);
		});
	});
};

interface Source_Properties {
	connectionID: string;
	sourceID: string;
}
