import { createSlice } from "@reduxjs/toolkit";
import { RootState } from "../store";
import * as esbuild from "esbuild-wasm";
import { unpkgFetchPlugin, unpkgPathPlugin } from "../../esbuild/plugins";
import { CompilerOutput, CompilerStatus } from "../../_types/compilerTypes";

type InitialStateType = {
  isInitializing: boolean;
  esbuildStatus: CompilerStatus;
  isCompiling: boolean;
  output: CompilerOutput;
};

const initialState = {
  isInitializing: false,
  esbuildStatus: { isReady: false, error: "" },
  isCompiling: false,
  output: { code: "", error: "" },
};

export const compilerSlice = createSlice({
  name: "compiler",
  initialState: initialState,
  reducers: {
    init_esbuild: (state: InitialStateType) => {
      state.isInitializing = true;
    },
    init_esbuild_success: (state: InitialStateType) => {
      state.esbuildStatus.isReady = true;
      state.esbuildStatus.error = "";
      state.isInitializing = false;
    },
    init_esbuild_failure: (state: InitialStateType, { payload }) => {
      state.esbuildStatus.isReady = false;
      state.esbuildStatus.error = payload;
      state.isInitializing = false;
    },
    compiled: (state: InitialStateType) => {
      state.isCompiling = true;
    },
    compiled_success: (state: InitialStateType, { payload }) => {
      state.output.code = payload;
      state.output.error = "";
      state.isCompiling = false;
    },
    compiled_failure: (state: InitialStateType, { payload }) => {
      state.output.code = "";
      state.output.error = payload;
      state.isCompiling = false;
    },
  },
});

export const {
  compiled,
  compiled_success,
  compiled_failure,
  init_esbuild,
  init_esbuild_success,
  init_esbuild_failure,
} = compilerSlice.actions;

export const compiler_state = (state: RootState) => state.compiler;

export default compilerSlice.reducer;

// Asynchronous thunk action

export function initEsbuild() {
  return async (dispatch: any) => {
    dispatch(init_esbuild());

    await esbuild
      .initialize({
        worker: true,
        wasmURL: "https://unpkg.com/esbuild-wasm@0.14.42/esbuild.wasm",
      })
      .then(() => {
        dispatch(init_esbuild_success());
      })
      .catch((error) => dispatch(init_esbuild_failure(error.message)));
  };
}

export function getCompileCode(rawCode: string, entryPoint: string) {
  return async (dispatch: any) => {
    dispatch(compiled());

    try {
      const result = await esbuild.build({
        entryPoints: [`${entryPoint}`],
        bundle: true,
        write: false,
        minify: true,
        outdir: "/",
        plugins: [unpkgPathPlugin(), unpkgFetchPlugin(rawCode, entryPoint)],
        metafile: true,
        allowOverwrite: true,
      });

      dispatch(compiled_success(result.outputFiles[0].text));
    } catch (error) {
      // @ts-ignore
      dispatch(compiled_failure(error.message));
    }
  };
}