type PathsType = {
  audioDirectory: string;
  cacheDirectory: string;
  configDirectory: string;
  dataDirectory: string;
  desktopDirectory: string;
  documentDirectory: string;
  downloadDirectory: string;
  executableDirectory: string;
  fontDirectory: string;
  homeDirectory: string;
  logDirectory: string;
  pictureDirectory: string;
  templateDirectory: string;
  videoDirectory: string;
};

const programTrailingPath = "stort/";

class Paths {
  private static instance: Paths;
  paths: PathsType | null = null;

  private constructor() {}

  static getInstance(): Paths {
    if (!Paths.instance) {
      Paths.instance = new Paths();
    }
    return Paths.instance;
  }

  async initialize(): Promise<void> {
    // avoid reinitialization if already doen
    if (this.paths) return;

    const {
      audioDir,
      cacheDir,
      configDir,
      dataDir,
      desktopDir,
      documentDir,
      downloadDir,
      executableDir,
      fontDir,
      homeDir,
      logDir,
      pictureDir,
      templateDir,
      videoDir,
    } = await import("@tauri-apps/api/path");

    try {
      this.paths = {
        audioDirectory: await audioDir(),
        cacheDirectory: (await cacheDir()) + programTrailingPath,
        configDirectory: (await configDir()) + programTrailingPath,
        dataDirectory: (await dataDir()) + programTrailingPath,
        desktopDirectory: await desktopDir(),
        documentDirectory: await documentDir(),
        downloadDirectory: await downloadDir(),
        executableDirectory: await executableDir(),
        fontDirectory: await fontDir(),
        homeDirectory: await homeDir(),
        logDirectory: await logDir(),
        pictureDirectory: await pictureDir(),
        templateDirectory: await templateDir(),
        videoDirectory: await videoDir(),
      };

      // make paths immutable
      Object.freeze(this.paths);
    } catch (error) {
      console.error("Error initializing paths:", error);
      throw error;
    }
  }

  getPath(key: keyof PathsType): string {
    if (!this.paths) {
      throw new Error("Paths are not initialized. Call initialize() first.");
    }
    return this.paths[key];
  }
}

export default Paths.getInstance();
