/*
 * Copyright (C) 2019-2022 Open StApps
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */
import {existsSync, PathLike} from 'fs';
import path from 'path';
import {readFile} from 'fs/promises';

/**
 * Get used version of a dependency of a project referenced by a path
 * @param directoryPath Path to a Node.js project directory
 * @param dependency Dependency to get used version of
 */
export async function getUsedVersion(directoryPath: PathLike, dependency: string): Promise<string> {
  if (!existsSync(path.join(directoryPath.toString(), 'package.json'))) {
    throw new Error(`'package.json' does not exist in '${directoryPath}'. Not a Node.js project?`);
  }

  const buffer = await readFile(path.join(directoryPath.toString(), 'package.json'));
  const content = buffer.toString();
  const packageJson = JSON.parse(content);

  if (typeof packageJson.dependencies !== 'object') {
    throw new TypeError(`Project in '${directoryPath}' has no dependencies!`);
  }

  if (typeof packageJson.dependencies[dependency] !== 'string') {
    throw new TypeError(`Project in '${directoryPath}' does not depend on '${dependency}'.`);
  }

  return packageJson.dependencies[dependency];
}

/**
 * Get 'MAJOR.MINOR' part of a used version
 *
 * See [[getUsedVersion]].
 * @param path see [[getUsedVersion]]
 * @param dependency see [[getUsedVersion]]
 */
export async function getUsedVersionMajorMinor(path: PathLike, dependency: string): Promise<string> {
  const usedVersions = await getUsedVersion(path, dependency);
  const versionMatch = usedVersions.match(/([0-9]+\.[0-9]+)\.[0-9]+/);

  // istanbul ignore if
  if (versionMatch === null) {
    throw new Error(`Used version of '${dependency}' of project in '${path}' could not be determined.`);
  }

  return versionMatch[1];
}
