import { SchematicsException, Tree } from '@angular-devkit/schematics';
import { WorkspaceSchema } from '@schematics/angular/utility/workspace-models';
import path from 'path';

/**
 * Parses a JSON string and returns the corresponding JavaScript object.
 * If the JSON string is invalid, an empty object is returned.
 * @param {string} json - The JSON string to parse.
 * @returns {object} - The parsed JavaScript object.
 */
export const parseJson = (json: string) => {
  try {
    return JSON.parse(json);
  } catch (e) {
    return {};
  }
};

export const getRootPath = (append?: string) => {
  return path.join(__dirname, '../../', append ?? '');
};

/**
 * Retrieves the path of the Angular workspace configuration file.
 * @param {Tree} host - The host tree representing the file system.
 * @returns {string} The path of the Angular workspace configuration file.
 */
const getWorkspacePath = (host: Tree) => {
  const possibleFiles = ['/angular.json', '/.angular.json'];
  const path = possibleFiles.filter(path => host.exists(path))[0];
  return path;
};

/**
 * Retrieves the workspace configuration from the given host.
 * @param {Tree} host - The host object representing the file system.
 * @returns The parsed workspace configuration object.
 * @throws {SchematicsException} If the workspace configuration file cannot be found.
 */
export const getWorkspace = (host: Tree) => {
  const path = getWorkspacePath(host);
  const configBuffer = host.read(path);
  if (configBuffer === null) {
    throw new SchematicsException(`Could not find (${path})`);
  }
  const content = configBuffer.toString();
  return parseJson(content);
};

/**
 * Checks if the given workspace object is a valid workspace schema.
 * @param {any} workspace - The workspace object to check.
 * @returns {boolean} - True if the workspace has a 'projects' property, false otherwise.
 */
const isWorkspaceSchema = (workspace: any) => {
  return !!(workspace.projects);
};

/**
 * Retrieves the project configuration object from the given workspace or host.
 * @param {WorkspaceSchema | Tree} workspaceOrHost - The workspace or host object.
 * @param {string} projectName - The name of the project to retrieve.
 * @returns The project configuration object.
 */
export const getProject = (workspaceOrHost: WorkspaceSchema | Tree, projectName: string) => {
  const workspace: any = isWorkspaceSchema(workspaceOrHost)
    ? workspaceOrHost
    : getWorkspace(workspaceOrHost as Tree);
  return workspace.projects[projectName];
};
