import RawIPC = require("node-ipc");
import { InternalService, Microservice } from "@autoplex/microservice";
import { IPC, IpcMessageHandler } from "./schema";

/**
 * An abstract IPC service containing common properties/methods among the server and client
 */
export default abstract class AbstractIpcService<M extends Microservice = Microservice> extends InternalService<M>
{
	/**
	 * The IPC instance
	 */
	private __ipc: IPC|null = null;

	// Implementation Requirements -----------------------------------------------------------------

	/**
	 * The path to the socket file
	 */
	protected abstract readonly SOCKET_PATH: string;

	/**
	 * Add a message handler for the service
	 */
	protected abstract addMessageHandler(method: string, handle: IpcMessageHandler): void;

	/**
	 * Boot the IPC service after configuration is complete
	 */
	protected abstract bootIpc(ipc: IPC): Promise<void>;

	/**
	 * Shutdown the IPC service before it is destroyed
	 */
	protected abstract shutdownIpc(ipc: IPC|null): Promise<void>;

	// Service Management --------------------------------------------------------------------------

	/**
	 * Boot the IPC service
	 */
	public async boot() {
		// Create the IPC socket
		this.__ipc = new RawIPC.IPC();
		this.__ipc.config.id = this.NAME;
		this.__ipc.config.retry = 1500;
		this.__ipc.config.silent = true;
		await this.bootIpc(this.__ipc);
	}

	/**
	 * Shutdown the IPC service
	 */
	public async shutdown() {
		await this.shutdownIpc(this.__ipc);
		this.__ipc = null;
	}

	// Accessors -----------------------------------------------------------------------------------

	/**
	 * Get the raw IPC instance
	 */
	protected get rawIpcInstance(): IPC|null {
		return this.__ipc;
	}
}
