// main/ipcMainHandler.settings.ts
import { dialog, IpcMainInvokeEvent } from "electron";
import log from "electron-log/main";
import _ from "lodash";
import Store from "../store/store";
import { getMainWindow } from "../util/toRenderer";
import {
  addWatcherPath,
  removeWatcherPath,
  StartWatcher,
  StopWatcher,
} from "../watcher/watcher";
import { PaintScaleConfig } from "./paintScale";


// Initialize paint scale input configs in store if not set
if (!Store.get("settings.paintScaleInputConfigs")) {
  Store.set("settings.paintScaleInputConfigs", []);
}

// Initialize paint scale output configs in store if not set
if (!Store.get("settings.paintScaleOutputConfigs")) {
  Store.set("settings.paintScaleOutputConfigs", []);
}

const SettingsWatchedFilePathsAdd = async (): Promise<string[]> => {
  const mainWindow = getMainWindow();
  if (!mainWindow) {
    log.error("No main window found when trying to open dialog");
    return [];
  }
  const result = await dialog.showOpenDialog(mainWindow, {
    properties: ["openDirectory"],
  });

  if (!result.canceled) {
    Store.set(
        "settings.filepaths",
        _.union(result.filePaths, Store.get("settings.filepaths")),
    );
    addWatcherPath(result.filePaths);
  }

  return Store.get("settings.filepaths");
};

const SettingsWatchedFilePathsRemove = async (
    _event: IpcMainInvokeEvent,
    path: string,
): Promise<string[]> => {
  Store.set(
      "settings.filepaths",
      _.without(Store.get("settings.filepaths"), path),
  );
  removeWatcherPath(path);
  return Store.get("settings.filepaths");
};

const SettingsWatchedFilePathsGet = async (): Promise<string[]> => {
  return Store.get("settings.filepaths") || [];
};

const SettingsWatcherPollingGet = async (): Promise<{
  enabled: boolean;
  interval: number;
}> => {
  const pollingEnabled: { enabled: boolean; interval: number } =
      Store.get("settings.polling");
  return { enabled: pollingEnabled.enabled, interval: pollingEnabled.interval };
};

const SettingsWatcherPollingSet = async (
    _event: IpcMainInvokeEvent,
    pollingSettings: {
      enabled: boolean;
      interval: number;
    },
): Promise<{
  enabled: boolean;
  interval: number;
}> => {
  log.info("Polling set", pollingSettings);
  const { enabled, interval } = pollingSettings;
  Store.set("settings.polling", { enabled, interval });

  await StopWatcher();
  await StartWatcher();

  return { enabled, interval };
};

const SettingsPpcFilePathGet = async (): Promise<string> => {
  return Store.get("settings.ppcFilePath");
};

const SettingsPpcFilePathSet = async (): Promise<string> => {
  const mainWindow = getMainWindow();
  if (!mainWindow) {
    log.error("No main window found when trying to open dialog");
    return "";
  }
  const result = await dialog.showOpenDialog(mainWindow, {
    properties: ["openDirectory"],
  });

  if (!result.canceled) {
    Store.set("settings.ppcFilePath", result.filePaths[0]);
  }

  return (Store.get("settings.ppcFilePath") as string) || "";
};

const SettingEmsOutFilePathGet = async (): Promise<string> => {
  return Store.get("settings.emsOutFilePath");
};

const SettingEmsOutFilePathSet = async (): Promise<string> => {
  const mainWindow = getMainWindow();
  if (!mainWindow) {
    log.error("No main window found when trying to open dialog");
    return "";
  }
  const result = await dialog.showOpenDialog(mainWindow, {
    properties: ["openDirectory"],
  });

  if (!result.canceled) {
    Store.set("settings.emsOutFilePath", result.filePaths[0]);
  }

  return (Store.get("settings.emsOutFilePath") as string) || "";
};

const SettingsPaintScaleInputConfigsGet = async (
    _event?: IpcMainInvokeEvent,
): Promise<PaintScaleConfig[]> => {
  try {
    const configs = Store.get("settings.paintScaleInputConfigs") as PaintScaleConfig[];
    log.debug("Retrieved paint scale input configs:", configs);
    return configs || [];
  } catch (error) {
    log.error("Error getting paint scale input configs:", error);
    throw error;
  }
};

const SettingsPaintScaleInputConfigsSet = async (
    _event: IpcMainInvokeEvent,
    configs: PaintScaleConfig[],
): Promise<boolean> => {
  try {
    Store.set("settings.paintScaleInputConfigs", configs);
    log.debug("Saved paint scale input configs:", configs);
    return true;
  } catch (error) {
    log.error("Error setting paint scale input configs:", error);
    throw error;
  }
};

const SettingsPaintScaleInputPathSet = async (
    _event: IpcMainInvokeEvent,
): Promise<string | null> => {
  try {
    const mainWindow = getMainWindow();
    if (!mainWindow) {
      log.error("No main window found when trying to open dialog");
      return null;
    }
    const result = await dialog.showOpenDialog(mainWindow, {
      properties: ["openDirectory"],
    });
    if (result.canceled) {
      log.debug("Paint scale input path selection canceled");
      return null;
    }
    const path = result.filePaths[0];
    log.debug("Selected paint scale input path:", path);
    return path;
  } catch (error) {
    log.error("Error setting paint scale input path:", error);
    throw error;
  }
};

const SettingsPaintScaleOutputConfigsGet = async (
    _event?: IpcMainInvokeEvent,
): Promise<PaintScaleConfig[]> => {
  try {
    const configs = Store.get("settings.paintScaleOutputConfigs") as PaintScaleConfig[];
    log.debug("Retrieved paint scale output configs:", configs);
    return configs || [];
  } catch (error) {
    log.error("Error getting paint scale output configs:", error);
    throw error;
  }
};

const SettingsPaintScaleOutputConfigsSet = async (
    _event: IpcMainInvokeEvent,
    configs: PaintScaleConfig[],
): Promise<boolean> => {
  try {
    Store.set("settings.paintScaleOutputConfigs", configs);
    log.debug("Saved paint scale output configs:", configs);
    return true;
  } catch (error) {
    log.error("Error setting paint scale output configs:", error);
    throw error;
  }
};

const SettingsPaintScaleOutputPathSet = async (
    _event: IpcMainInvokeEvent,
): Promise<string | null> => {
  try {
    const mainWindow = getMainWindow();
    if (!mainWindow) {
      log.error("No main window found when trying to open dialog");
      return null;
    }
    const result = await dialog.showOpenDialog(mainWindow, {
      properties: ["openDirectory"],
    });
    if (result.canceled) {
      log.debug("Paint scale output path selection canceled");
      return null;
    }
    const path = result.filePaths[0];
    log.debug("Selected paint scale output path:", path);
    return path;
  } catch (error) {
    log.error("Error setting paint scale output path:", error);
    throw error;
  }
};

export {
  SettingsPpcFilePathGet,
  SettingsPpcFilePathSet,
  SettingsWatchedFilePathsAdd,
  SettingsWatchedFilePathsGet,
  SettingsWatchedFilePathsRemove,
  SettingsWatcherPollingGet,
  SettingsWatcherPollingSet,
  SettingEmsOutFilePathGet,
  SettingEmsOutFilePathSet,
  SettingsPaintScaleInputConfigsGet,
  SettingsPaintScaleInputConfigsSet,
  SettingsPaintScaleInputPathSet,
  SettingsPaintScaleOutputConfigsGet,
  SettingsPaintScaleOutputConfigsSet,
  SettingsPaintScaleOutputPathSet,
};