import { gte, valid } from 'semver';
import { config, LibTypeEnum } from 'tnp-core/lib';
import { Helpers, Utils, _, crossPlatformPath, fg, path, } from 'tnp-core/lib';
import { BasePackageJson, UtilsNpm, } from 'tnp-helpers/lib';
import { binMainProject, scriptsCommands } from '../../constants';
export class PackageJSON extends BasePackageJson {
    project;
    KEY_TNP_PACKAGE_JSON = 'tnp';
    constructor(options, project) {
        super(options);
        this.project = project;
    }
    updateDataFromTaonJson() {
        if (this.project.taonJson.exists) {
            const packageJsonOverride = this.project.taonJson.overridePackageJsonManager.getAllData();
            if (_.isObject(packageJsonOverride) && !_.isArray(packageJsonOverride)) {
                this.data = _.merge(this.data, packageJsonOverride);
            }
        }
    }
    setDataFromCoreContainer() {
        if (this.project.framework.isCoreProject &&
            this.project.framework.isContainer) {
            return; // do not update from core container
        }
        if (this.project.framework.coreContainer.taonJson.exists) {
            const packageJsonOverride = this.project.framework.coreContainer.taonJson.overridePackageJsonManager.getAllData();
            if (_.isObject(packageJsonOverride) && !_.isArray(packageJsonOverride)) {
                this.data = packageJsonOverride;
            }
        }
    }
    recreateBin() {
        // Helpers.taskStarted('Recreating bin...');
        const pattern = `${this.project.pathFor(binMainProject)}/*`;
        const countLinkInPackageJsonBin = fg
            .sync(pattern)
            .map(f => crossPlatformPath(f))
            .filter(f => {
            return (Helpers.readFile(f) || '').startsWith('#!/usr/bin/env');
        });
        const bin = {};
        countLinkInPackageJsonBin.forEach(p => {
            bin[path.basename(p)] = `${binMainProject}/${path.basename(p)}`;
        });
        // Helpers.taskDone('done recreating bin...');
        return bin;
    }
    saveToDisk(purpose) {
        //#region @backendFunc
        if (this.project.framework.isStandaloneProject ||
            this.project.framework.isContainer) {
            const versionToPreserve = this.data.version;
            delete this.data[this.KEY_TNP_PACKAGE_JSON];
            this.setDataFromCoreContainer();
            this.updateDataFromTaonJson();
            for (const depTyp of this.dependenciesTypesArray) {
                const depObj = this.data[depTyp];
                if (_.isObject(depObj)) {
                    for (const depName in depObj) {
                        if (_.isNil(depObj[depName])) {
                            delete depObj[depName];
                        }
                    }
                }
            }
            this.data.name = this.project.nameForNpmPackage;
            this.data.version = versionToPreserve;
            if (!this.data.version) {
                try {
                    const latestTag = (this.project.git.lastTagVersionName || '').replace('v', '');
                    if (UtilsNpm.isProperVersion(latestTag)) {
                        this.data.version = latestTag;
                    }
                }
                catch (error) { }
            }
            if (!this.data.version) {
                this.data.version = '0.0.0';
            }
            this.data.main = 'dist/app.electron.js'; // fix for electron
            const showFirst = [
                'name',
                'version',
                'scripts',
                'license',
                'author',
                'private',
                'homepage',
            ];
            const sorted = Utils.sortKeys(_.cloneDeep(this.data));
            for (const key of showFirst) {
                delete sorted[key];
            }
            const destinationObject = {
                ...showFirst.reduce((acc, key) => {
                    acc[key] = this.data[key];
                    return acc;
                }, {}),
                ...sorted,
            };
            destinationObject.scripts = destinationObject.scripts || {};
            if (this.project.taonJson.type === LibTypeEnum.ISOMORPHIC_LIB) {
                for (const command of scriptsCommands) {
                    destinationObject.scripts[command] = command;
                }
            }
            destinationObject.bin = this.recreateBin();
            // TODO this causes issues with export js
            delete destinationObject.exports;
            // destinationObject.exports = {
            //   '.': {
            //     style: './scss/index.scss',
            //   },
            // };
            this.data = destinationObject;
        }
        super.saveToDisk();
        //#endregion
    }
    resolvePossibleNewVersion(releaseVersionBumpType) {
        //#region @backendFunc
        const pj = new BasePackageJson({
            jsonContent: {
                version: this.project.packageJson.getBumpedVersionFor(releaseVersionBumpType),
            },
            reloadInMemoryCallback: data => {
                // console.log('new pj data', data);
            },
        });
        const lastTagVersion = this.project.git.lastTagVersionName.trim().replace('v', '') || '0.0.0';
        if (valid(lastTagVersion) === null) {
            Helpers.warn(`[${config.frameworkName}]

        Last tag may not be proper version: "${lastTagVersion}"

        `);
            return pj.version;
        }
        const pjtag = new BasePackageJson({
            jsonContent: { version: lastTagVersion },
            reloadInMemoryCallback: data => {
                // console.log('new pj data', data);
            },
        });
        if (pjtag.version) {
            pjtag.setVersion(pjtag.getBumpedVersionFor(releaseVersionBumpType));
        }
        let i = 0;
        while (true) {
            if (i++ > 10) {
                Helpers.logInfo('Resolving new version...');
            }
            if (!pjtag.version) {
                return pj.version;
            }
            // console.log(`pj.version`, pj.version);
            // console.log(`pjtag.version`, pjtag.version);
            if (gte(pj.version, pjtag.version)) {
                return pj.version;
            }
            pj.setVersion(pjtag.version);
        }
        //#endregion
    }
}
//# sourceMappingURL=package-json.js.map