import axios from 'axios';

export class Getiyo {
	serverProtocol: 'http' | 'https';
	serverAddress: string;
	serverPort: number;
	channelName: string;
	channelApiKey: string;

	constructor(settings: {
		serverProtocol: 'http' | 'https';
		serverAddress: string;
		serverPort: number;
		channelName: string;
		channelApiKey: string;
	}) {
		this.serverProtocol = settings.serverProtocol != undefined ? settings.serverProtocol : 'http';
		this.serverAddress = settings.serverAddress;
		this.serverPort = settings.serverPort;
		this.channelName = settings.channelName;
		this.channelApiKey = settings.channelApiKey;
	}

	_getBaseURI() {
		return `${this.serverProtocol}://${this.serverAddress}:${this.serverPort}/${this.channelName}/api/v1/${this
			.channelApiKey}/`;
	}

	checkConnection(callback: (succeed: boolean) => void) {
		axios.get(this._getBaseURI()).then(() => callback(true)).catch(() => callback(false));
	}

	getScenes(): Promise<{ id: string; name: string }[]> {
		return new Promise((resolve, reject) => {
			axios
				.get(this._getBaseURI() + 'scenes')
				.then((response) => {
					if (response.data.succeed == true) {
						resolve(response.data.response);
					} else reject(new Error('Unable to connection to Getiyo instance'));
				})
				.catch(reject);
		});
	}

	getDisplays(): Promise<{ id: string; name: string; scene: string }[]> {
		return new Promise((resolve, reject) => {
			axios
				.get(this._getBaseURI() + 'displays')
				.then((response) => {
					if (response.data.succeed == true) {
						resolve(response.data.response);
					} else reject(new Error('Unable to connection to Getiyo instance'));
				})
				.catch(reject);
		});
	}

	getModules(): Promise<
		{
			moduleID: string;
			name: string;
			type: string;
			triggers: { [triggerID: string]: { type: string; description: string; arguments: any[] } };
		}[]
	> {
		return new Promise((resolve, reject) => {
			axios
				.get(this._getBaseURI() + 'modules')
				.then((response) => {
					if (response.data.succeed == true) {
						resolve(response.data.response);
					} else reject(new Error('Unable to connection to Getiyo instance'));
				})
				.catch(reject);
		});
	}

	getTimelineSections(): Promise<string[]> {
		return new Promise((resolve, reject) => {
			axios
				.get(this._getBaseURI() + 'timeline/sections')
				.then((response) => {
					if (response.data.succeed == true) {
						resolve(response.data.response);
					} else reject(new Error('Unable to connection to Getiyo instance'));
				})
				.catch(reject);
		});
	}

	publishScene(sceneID: string, displayID: string): Promise<void> {
		return new Promise((resolve, reject) => {
			axios
				.get(this._getBaseURI() + `scenes/publish/${sceneID}/${displayID}`)
				.then((response) => {
					if (response.data.succeed == true) {
						resolve();
					} else reject(new Error('Unable to connection to Getiyo instance'));
				})
				.catch(reject);
		});
	}

	startTimeline(createNewRunner: boolean = false): Promise<void> {
		return new Promise((resolve, reject) => {
			axios
				.get(this._getBaseURI() + `timeline/start/${createNewRunner}`)
				.then((response) => {
					if (response.data.succeed == true) {
						resolve();
					} else reject(new Error('Unable to connection to Getiyo instance'));
				})
				.catch(reject);
		});
	}

	stopTimeline(runnerID: string = 'main'): Promise<void> {
		return new Promise((resolve, reject) => {
			axios
				.get(this._getBaseURI() + `timeline/stop/${runnerID}`)
				.then((response) => {
					if (response.data.succeed == true) {
						resolve();
					} else reject(new Error('Unable to connection to Getiyo instance'));
				})
				.catch(reject);
		});
	}

	pauseTimeline(runnerID: string = 'main'): Promise<void> {
		return new Promise((resolve, reject) => {
			axios
				.get(this._getBaseURI() + `timeline/pause/${runnerID}`)
				.then((response) => {
					if (response.data.succeed == true) {
						resolve();
					} else reject(new Error('Unable to connection to Getiyo instance'));
				})
				.catch(reject);
		});
	}

	skipTimelineBlock(runnerID: string = 'main'): Promise<void> {
		return new Promise((resolve, reject) => {
			axios
				.get(this._getBaseURI() + `timeline/skip/${runnerID}`)
				.then((response) => {
					if (response.data.succeed == true) {
						resolve();
					} else reject(new Error('Unable to connection to Getiyo instance'));
				})
				.catch(reject);
		});
	}

	continueTimelineHold(runnerID: string = 'main'): Promise<void> {
		return new Promise((resolve, reject) => {
			axios
				.get(this._getBaseURI() + `timeline/hold/${runnerID}`)
				.then((response) => {
					if (response.data.succeed == true) {
						resolve();
					} else reject(new Error('Unable to connection to Getiyo instance'));
				})
				.catch(reject);
		});
	}

	jumpToTimelineSections(sectionName: string, runnerID: string = 'main'): Promise<void> {
		return new Promise((resolve, reject) => {
			axios
				.get(this._getBaseURI() + `timeline/sections/jump/${encodeURI(sectionName)}/${runnerID}`)
				.then((response) => {
					if (response.data.succeed == true) {
						resolve();
					} else reject(new Error('Unable to connection to Getiyo instance'));
				})
				.catch(reject);
		});
	}
}
