import Channel from "../channel.js";
import {
	cancelGame,
	checkTimeout,
	gameReady,
	isValidUpdateKey,
	isValidUpdateValue,
	putStone,
	updateSettings,
} from "@/services/reversi/index.js";
import type { StreamMessages } from "../types.js";

export default class extends Channel {
	public readonly chName = "reversiGame";
	public static shouldShare = false;
	public static requireCredential = false;
	private gameId: string | null = null;

	constructor(id: string, connection: Channel["connection"]) {
		super(id, connection);
		this.onEvent = this.onEvent.bind(this);
	}

	public async init(params: any) {
		if (typeof params.gameId !== "string") return;
		this.gameId = params.gameId;
		this.subscriber.on(`reversiGameStream:${this.gameId}`, this.onEvent);
	}

	private onEvent(data: StreamMessages["reversiGame"]["payload"]) {
		this.send(data);
	}

	public onMessage(type: string, body: any) {
		if (!this.gameId) return;
		switch (type) {
			case "ready":
				if (this.user && typeof body === "boolean") gameReady(this.gameId, this.user, body);
				break;
			case "updateSettings":
				if (
					this.user &&
					body &&
					isValidUpdateKey(body.key) &&
					isValidUpdateValue(body.key, body.value)
				) {
					updateSettings(this.gameId, this.user, body.key, body.value);
				}
				break;
			case "cancel":
				if (this.user) cancelGame(this.gameId, this.user);
				break;
			case "putStone":
				if (this.user && body && typeof body.pos === "number") {
					putStone(this.gameId, this.user, body.pos, typeof body.id === "string" ? body.id : null);
				}
				break;
			case "claimTimeIsUp":
				checkTimeout(this.gameId);
				break;
		}
	}

	public dispose() {
		if (this.gameId) {
			this.subscriber.off(`reversiGameStream:${this.gameId}`, this.onEvent);
		}
	}
}
