import { InfrastructureError } from "../../infrastructure/InfrastructureError";
import { RepositoryBuilder } from "./RepositoryBuilder";

export interface IRepositoryManager {
  getRepository: <T>(name: string) => RepositoryBuilder<T>;
  registerRepository: <T>(
    name: string,
    repository: RepositoryBuilder<T>,
  ) => void;
}

export class RepositoryManager implements IRepositoryManager {
  private static instance: RepositoryManager | null = null;
  public static getInstance(): RepositoryManager {
    if (!RepositoryManager.instance) {
      RepositoryManager.instance = new RepositoryManager();
    }

    return RepositoryManager.instance;
  }

  private repositories: Map<string, RepositoryBuilder<any>>;

  private constructor() {
    this.repositories = new Map();
  }

  public registerRepository<T>(
    name: string,
    repository: RepositoryBuilder<T>,
  ): void {
    if (!this.repositories.has(name)) {
      this.repositories.set(name, repository);
    }
  }

  public getRepository<T>(name: string): RepositoryBuilder<T> {
    const repository = this.repositories.get(name) as RepositoryBuilder<T>;

    if (!repository) {
      throw InfrastructureError.create(
        InfrastructureError.RESOURCE_NOT_FOUND_ERROR,
        `Repository "${name}" not found.`,
      );
    }

    return repository;
  }
}
