import React from 'react';
import { getState, setState, updateState } from '../common/cache';
import { getMessageHandler, MessageHandler } from '../common/message';
import { MergeRequestState } from '../common/types';

class MergeRequestContext {
	private handler: MessageHandler;

	constructor(
		public mrState: MergeRequestState = getState(),
		public onchange?: (ctx: MergeRequestState) => void,
		handler?: MessageHandler,
	) {
		this.handler = handler ?? getMessageHandler(this.handleMessage);
	}

	setMr = (mr: MergeRequestState) => {
		this.mrState = mr;
		setState(this.mrState);
		if (this.onchange) {
			this.onchange(this.mrState);
		}
		return this;
	};

	postMessage(message: { command: string; args?: Record<string, any> | string }): Promise<any> {
		return this.handler.postMessage(message);
	}

	handleMessage = (message: any) => {
		switch (message.command) {
			case 'mr.initialize':
				return this.setMr(message.state);
			case 'update-state':
				return this.updateMR(message.state);
		}
	};

	updateMR = (mrState: Partial<MergeRequestState>) => {
		updateState(mrState);
		this.mrState = { ...this.mrState, ...mrState };
		if (this.onchange) {
			this.onchange(this.mrState);
		}
		return this;
	};

	public mergeBranch = (branchs: { head: string; base: string }) =>
		this.postMessage({ command: 'mr.mergeBranch', args: branchs });

	public openMergeEditor = (file: string) => this.postMessage({ command: 'mr.openMergeEditor', args: { file } });

	public checkLocalMergeStatus = () => this.postMessage({ command: 'mr.checkLocalMergeStatus' });

	public getLocalConflictFileList = () => this.postMessage({ command: 'mr.getLocalConflictFileList' });

	public mergeCommitAndPush = () => this.postMessage({ command: 'mr.mergeCommitAndPush' });

	public refresh = () => this.postMessage({ command: 'mr.refresh' });

	addComment() {
		console.log('addComment');
	}

	public approve = async (commentMessage = '') => {
		await this.postMessage({ command: 'mr.approve', args: { comment: commentMessage } });
	};

	public close = async () => {
		await this.postMessage({ command: 'mr.close' });
	};

	public exitReviewMode = async () => {
		await this.postMessage({ command: 'mr.exitReviewMode' });
	};
}

export const MrContext = React.createContext<MergeRequestContext>(new MergeRequestContext());
