import { loadTextFile, saveTextFile } from "./file-service.js";
import {
  gcodeProgramPath,
  machineIniPath,
  parameterFilePath,
  splitOpfsPath,
  toolTablePath,
} from "./path-model.js";

const GCODE_PROGRAM_ROOT = ["linuxcnc", "gcode"];

const MACHINE_FILE_PATHS = {
  ini: machineIniPath,
  toolTable: toolTablePath,
  parameters: parameterFilePath,
};

export function machineFilePaths(machineId) {
  return {
    ini: machineIniPath(machineId),
    toolTable: toolTablePath(machineId),
    parameters: parameterFilePath(machineId),
  };
}

export async function saveMachineTextFiles(machineId, files, options = {}) {
  if (files === null || typeof files !== "object" || Array.isArray(files)) {
    throw new Error("machine files must be a plain object.");
  }

  const paths = machineFilePaths(machineId);
  for (const [name, pathFor] of Object.entries(MACHINE_FILE_PATHS)) {
    if (Object.hasOwn(files, name)) {
      await saveTextFile(pathFor(machineId), String(files[name]), options.storage);
    }
  }
  return paths;
}

export async function loadMachineTextFiles(machineId, options = {}) {
  const paths = machineFilePaths(machineId);
  return {
    ini: await loadTextFile(paths.ini, options.storage),
    toolTable: await loadTextFile(paths.toolTable, options.storage),
    parameters: await loadTextFile(paths.parameters, options.storage),
  };
}

export function gcodeFilenameFromProgramPath(path) {
  const parts = splitOpfsPath(path);
  if (
    parts.length !== 3 ||
    parts[0] !== GCODE_PROGRAM_ROOT[0] ||
    parts[1] !== GCODE_PROGRAM_ROOT[1]
  ) {
    throw new Error(`Invalid G-code program OPFS path: ${path}`);
  }
  return parts[2];
}

export async function saveGcodeProgram(filename, text, options = {}) {
  const path = gcodeProgramPath(filename);
  await saveTextFile(path, text, options.storage);
  return path;
}

export async function loadGcodeProgram(filename, options = {}) {
  return loadTextFile(gcodeProgramPath(filename), options.storage);
}
