"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PackagePlugin = void 0;
const Path = require("path");
const FS = require("fs");
const components_1 = require("../components");
const converter_1 = require("../converter");
const utils_1 = require("../../utils");
const fs_1 = require("../../utils/fs");
const paths_1 = require("../../utils/paths");
/**
 * A handler that tries to find the package.json and readme.md files of the
 * current project.
 */
let PackagePlugin = class PackagePlugin extends components_1.ConverterComponent {
    /**
     * Create a new PackageHandler instance.
     */
    initialize() {
        this.listenTo(this.owner, {
            [converter_1.Converter.EVENT_BEGIN]: this.onBegin,
            [converter_1.Converter.EVENT_RESOLVE_BEGIN]: this.onBeginResolve,
            [converter_1.Converter.EVENT_END]: () => {
                delete this.readmeFile;
                delete this.packageFile;
            },
        });
    }
    /**
     * Triggered when the converter begins converting a project.
     */
    onBegin(_context) {
        this.readmeFile = undefined;
        this.packageFile = undefined;
        // Path will be resolved already. This is kind of ugly, but...
        const noReadmeFile = this.readme.endsWith("none");
        if (!noReadmeFile && this.readme) {
            if (FS.existsSync(this.readme)) {
                this.readmeFile = this.readme;
            }
        }
        const packageAndReadmeFound = () => (noReadmeFile || this.readmeFile) && this.packageFile;
        const reachedTopDirectory = (dirName) => dirName === Path.resolve(Path.join(dirName, ".."));
        let dirName = Path.resolve((0, fs_1.getCommonDirectory)(this.application.options.getValue("entryPoints")));
        this.application.logger.verbose(`Begin readme.md/package.json search at ${(0, paths_1.nicePath)(dirName)}`);
        while (!packageAndReadmeFound() && !reachedTopDirectory(dirName)) {
            FS.readdirSync(dirName).forEach((file) => {
                const lowercaseFileName = file.toLowerCase();
                if (!noReadmeFile &&
                    !this.readmeFile &&
                    lowercaseFileName === "readme.md") {
                    this.readmeFile = Path.join(dirName, file);
                }
                if (!this.packageFile && lowercaseFileName === "package.json") {
                    this.packageFile = Path.join(dirName, file);
                }
            });
            dirName = Path.resolve(Path.join(dirName, ".."));
        }
    }
    /**
     * Triggered when the converter begins resolving a project.
     *
     * @param context  The context object describing the current state the converter is in.
     */
    onBeginResolve(context) {
        const project = context.project;
        if (this.readmeFile) {
            project.readme = (0, utils_1.readFile)(this.readmeFile);
        }
        if (this.packageFile) {
            project.packageInfo = JSON.parse((0, utils_1.readFile)(this.packageFile));
            if (!project.name) {
                if (!project.packageInfo.name) {
                    context.logger.warn('The --name option was not specified, and package.json does not have a name field. Defaulting project name to "Documentation".');
                    project.name = "Documentation";
                }
                else {
                    project.name = String(project.packageInfo.name);
                }
            }
            if (this.includeVersion) {
                if (project.packageInfo.version) {
                    project.name = `${project.name} - v${project.packageInfo.version}`;
                }
                else {
                    context.logger.warn("--includeVersion was specified, but package.json does not specify a version.");
                }
            }
        }
        else {
            if (!project.name) {
                context.logger.warn('The --name option was not specified, and no package.json was found. Defaulting project name to "Documentation".');
                project.name = "Documentation";
            }
            if (this.includeVersion) {
                context.logger.warn("--includeVersion was specified, but no package.json was found. Not adding package version to the documentation.");
            }
        }
    }
};
__decorate([
    (0, utils_1.BindOption)("readme")
], PackagePlugin.prototype, "readme", void 0);
__decorate([
    (0, utils_1.BindOption)("includeVersion")
], PackagePlugin.prototype, "includeVersion", void 0);
PackagePlugin = __decorate([
    (0, components_1.Component)({ name: "package" })
], PackagePlugin);
exports.PackagePlugin = PackagePlugin;
