import { ipcMain } from 'electron';
import { app, BrowserWindow } from 'electron';
import { EVENT_NAMES } from '../../constants/define';
import BaseGenerator from '../code-generator/base-generator';
const path = require('path');
const puppeteer = require('puppeteer-core');

const {
  ON_CLOSE_RECORDER,
  ON_UPDATE_EVENT_LOG,
  ON_UPDATE_SELECTOR,
  RECORD,
  REPLAY,
  PAUSE,
  RESUME,
  INDICATE_SELECTOR,
  STOP,
} = EVENT_NAMES.CLIENT_RECORDER;

const InitRecorder = (pie, mainWindow) => {
  const handleOpenBrowser = async (_, url, mainWindow) => {
    try {
      const browser = await pie.connect(app, puppeteer);

      const browserWindow = new BrowserWindow({
        width: 1300,
        height: 1000,
        webPreferences: {
          preload: path.join(__dirname, 'preload2.js'),
        },
      });

      const page = await pie.getPage(browser, browserWindow);

      let eventLog = [];

      await page.exposeFunction('onUpdateEvents', (newEventLog) => {
        mainWindow.webContents.send(ON_UPDATE_EVENT_LOG, newEventLog);
        eventLog = newEventLog;
      });

      page.on('domcontentloaded', async () => {
        await page.evaluate((eventLog) => {
          window.headlessRecorder.init(window.onUpdateEvents, eventLog);
        }, eventLog);
      });

      // if (process.env.NODE_ENV === 'development') {
      //   browserWindow.webContents.openDevTools();
      // }

      const stop = async () => {
        page?.close();
        browserWindow?.close();
      };
      const pause = async () => {
        await page.evaluate(async () => {
          await window.headlessRecorderAPI.pause();
        });
      };

      const resume = async () => {
        await page.evaluate(async () => await window.headlessRecorderAPI.resume());
      };

      ipcMain.on(STOP, stop);

      ipcMain.on(PAUSE, pause);

      ipcMain.on(RESUME, resume);

      page.on('close', async () => {
        ipcMain.removeListener(STOP, stop);
        ipcMain.removeListener(PAUSE, pause);
        ipcMain.removeListener(RESUME, resume);
        mainWindow.webContents.send(ON_CLOSE_RECORDER, 1);
      });
      await page.goto(url, { waitUntil: 'networkidle0' });
    } catch (error) {
      console.log('Error at record ', { error });
    }
  };

  const handleReplay = async (eventLogs, isUsingLoader = true, stepId, isPreview) => {
    try {
      if (stepId) {
        eventLogs = eventLogs.filter((eventLog) => {
          if (isPreview) return eventLog.id <= stepId;
          return eventLog.id < stepId;
        });
      }

      const browser = await pie.connect(app, puppeteer);
      const browserWindow = new BrowserWindow({
        width: 1300,
        height: 1000,
        webPreferences: {
          preload: path.join(__dirname, 'preload2.js'),
        },
      });

      // if (process.env.NODE_ENV === 'development') {
      //   browserWindow.webContents.openDevTools();
      // }

      const page = await pie.getPage(browser, browserWindow);

      // initial loading
      await page.evaluate(async () => {
        await window.headlessRecorder?.initLoader();
      });

      if (isUsingLoader) {
        // loading every page
        page.on('domcontentloaded', async () => {
          await page.evaluate(async () => {
            await window.headlessRecorder?.initLoader();
          });
        });
      }

      const baseGenerator = new BaseGenerator();
      let code = baseGenerator._parseEvents(eventLogs);
      const wrappedHeader = `(async () => {\n
        try {`;
      const wrappedFooter = `\n
      } catch (error) {
        console.log('Error at replay ', { error });
      }
})()`;
      code = wrappedHeader + code + wrappedFooter;
      const func = new Function('page', code);
      await func(page);

      return page;
    } catch (error) {
      console.log('Error at replay ', { error });
    }
  };

  const handleReIndicateSelector = async (eventLogs, stepId, reSelectType = 'all') => {
    try {
      const page = await handleReplay(eventLogs, false, stepId, reSelectType === 'all');
      await page.exposeFunction('onUpdateSelector', (type, selector) => {
        console.log({ type, selector });
        mainWindow.webContents.send(ON_UPDATE_SELECTOR, type, selector);
      });

      page.on('domcontentloaded', async () => {
        await page.evaluate(
          async (eventLogs, stepId, reSelectType) => {
            await window.headlessRecorder.record(
              null,
              eventLogs,
              true,
              false,
              stepId,
              reSelectType,
              window.onUpdateSelector,
            );
          },
          eventLogs,
          stepId,
          reSelectType,
        );
      });
    } catch (error) {
      console.log('Error at select next page element ', { error });
    }
  };

  ipcMain.on(RECORD, (_, url) => handleOpenBrowser(_, url, mainWindow));
  ipcMain.on(REPLAY, async (_, eventLogs) => await handleReplay(eventLogs));
  ipcMain.on(INDICATE_SELECTOR, (_, eventLogs, stepId, reSelectType) =>
    handleReIndicateSelector(eventLogs, stepId, reSelectType),
  );
};

export default InitRecorder;
