import { join } from 'path';
import { Main } from '../Main';
import { pathExists, readJSON, writeFile, writeJSON } from 'fs-extra';
import { StartOrigin } from '../Unity/UnityRunner';

const PREFIX = '[Main]';
export class Timer {
	private _Main: Main;

	private configPath: string;

	private start: {
		hour: number;
		minute: number;
	} = {
		hour: null,
		minute: null,
	};
	private end: {
		hour: number;
		minute: number;
	} = {
		hour: null,
		minute: null,
	};

	constructor(Main: Main) {
		this._Main = Main;
		this.configPath = join(this._Main.dataPath, 'timer.json');
	}

	getState() {
		return {
			start: this.start,
			end: this.end,
		};
	}

	setStart(data: { hour: number; minute: number }) {
		this.start = data;
		this._Main.WebServer.socket.emit('timer', this.getState());
		this.save();
	}

	setEnd(data: { hour: number; minute: number }) {
		this.end = data;
		this._Main.WebServer.socket.emit('timer', this.getState());
		this.save();
	}

	startClock() {
		setInterval(() => {
			const startTime = new Date();
			startTime.setHours(this.start.hour, this.start.minute, 0, 0);

			const endTime = new Date();
			endTime.setHours(this.end.hour, this.end.minute, 0, 0);

			const shouldBeStarted =
				startTime <= new Date() && endTime > new Date();

			if (shouldBeStarted) {
				if (
					this._Main.UnityRunner.state !== 'RUNNING' &&
					this._Main.UnityRunner.state !== 'STARTING'
				) {
					console.log(PREFIX, 'Starting Unity');
					this._Main.UnityRunner.start(StartOrigin.Timer);
				} else if (
					this._Main.UnityRunner.startOrigin !== StartOrigin.Timer
				) {
					console.log(PREFIX, 'Already running');
					this._Main.UnityRunner.startOrigin = StartOrigin.Timer;
				}
			} else {
				if (
					this._Main.UnityRunner.state === 'RUNNING' &&
					this._Main.UnityRunner.startOrigin === StartOrigin.Timer
				) {
					console.log(PREFIX, 'Stopping Unity');

					this._Main.UnityWebSocket.quitApplication();
					this._Main.UnityRunner.startOrigin = null;
					this._Main.UnityRunner.state = 'STOPPED';

					setTimeout(() => {
						this._Main.UnityRunner.requestStop();
					}, 5000);
				}
			}
		}, 5000);
	}

	async load() {
		console.log(PREFIX, 'Loading timer configuration...');
		const exists = await pathExists(this.configPath);
		if (!exists) {
			this.save();
			return this.startClock();
		}

		const data = await readJSON(this.configPath);
		this.start = data.start;
		this.end = data.end;

		this.startClock();
	}

	private _save: NodeJS.Timeout;
	async save() {
		if (this._save) clearTimeout(this._save);

		this._save = setTimeout(async () => {
			writeFile(
				this.configPath,
				JSON.stringify({ start: this.start, end: this.end }, null, 4),
			);
		}, 1000);
	}
}
