/**
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.
*/

const fs = require('node:fs');
const path = require('node:path');
const cordova_util = require('./util');
const ConfigParser = require('cordova-common').ConfigParser;
const events = require('cordova-common').events;
const semver = require('semver');
const detectIndent = require('detect-indent');
const detectNewline = require('detect-newline');
const stringifyPackage = require('stringify-package');
const writeFileAtomicSync = require('write-file-atomic').sync;

exports.installPluginsFromConfigXML = installPluginsFromConfigXML;
exports.installPlatformsFromConfigXML = installPlatformsFromConfigXML;

// Install platforms looking at config.xml and package.json (if there is one).
function installPlatformsFromConfigXML (platforms, opts) {
    events.emit('verbose', 'Checking for saved platforms that haven\'t been added to the project');

    const installAllPlatforms = !platforms || platforms.length === 0;
    const projectRoot = cordova_util.getProjectRoot();
    const platformRoot = path.join(projectRoot, 'platforms');
    const pkgJsonPath = path.join(projectRoot, 'package.json');
    const confXmlPath = cordova_util.projectConfig(projectRoot);
    const cfg = new ConfigParser(confXmlPath);

    let pkgJson = {};
    let indent = '  ';
    let newline = '\n';

    if (fs.existsSync(pkgJsonPath)) {
        const fileData = fs.readFileSync(pkgJsonPath, 'utf8');
        indent = detectIndent(fileData).indent;
        newline = detectNewline(fileData);
        pkgJson = JSON.parse(fileData);
    } else {
        if (cfg.packageName()) {
            pkgJson.name = cfg.packageName().toLowerCase();
        }

        if (cfg.version()) {
            pkgJson.version = cfg.version();
        }

        if (cfg.name()) {
            pkgJson.displayName = cfg.name();
        }
    }

    pkgJson.dependencies = pkgJson.dependencies || {};
    pkgJson.devDependencies = pkgJson.devDependencies || {};
    pkgJson.cordova = pkgJson.cordova || {};
    pkgJson.cordova.platforms = pkgJson.cordova.platforms || [];

    const pkgPlatforms = pkgJson.cordova.platforms.slice();
    const pkgSpecs = Object.assign({}, pkgJson.dependencies, pkgJson.devDependencies);

    // Check for platforms listed in config.xml
    const cfgPlatforms = cfg.getEngines();

    cfgPlatforms.forEach(engine => {
        const platformModule = engine.name.startsWith('cordova-') ? engine.name : `cordova-${engine.name}`;

        // If package.json includes the platform, we use that config
        // Otherwise, we need to add the platform to package.json
        if (!pkgPlatforms.includes(engine.name) || (engine.spec && !(platformModule in pkgSpecs))) {
            events.emit('info', `Platform '${engine.name}' found in config.xml... Migrating it to package.json`);

            // If config.xml has a spec for the platform and package.json has
            // not, add the spec to devDependencies of package.json
            if (engine.spec && !(platformModule in pkgSpecs)) {
                pkgJson.devDependencies[platformModule] = engine.spec;
            }

            if (!pkgPlatforms.includes(engine.name)) {
                pkgJson.cordova.platforms.push(engine.name);
            }
        }
    });

    // Now that platforms have been updated, re-fetch them from package.json
    const platformIDs = pkgJson.cordova.platforms.slice();

    if (platformIDs.length !== pkgPlatforms.length) {
        // We've modified package.json and need to save it
        writeFileAtomicSync(pkgJsonPath, stringifyPackage(pkgJson, indent, newline), { encoding: 'utf8' });
    }

    const specs = Object.assign({}, pkgJson.dependencies || {}, pkgJson.devDependencies);

    const platformInfo = platformIDs.map(plID => ({
        name: plID,
        spec: specs[`cordova-${plID}`] || specs[plID]
    }));

    let platformName = '';

    function restoreCallback (platform) {
        platformName = platform.name;

        const platformPath = path.join(platformRoot, platformName);
        if (fs.existsSync(platformPath) || (!installAllPlatforms && !platforms.includes(platformName))) {
            // Platform already exists
            return Promise.resolve();
        }

        events.emit('log', `Discovered platform "${platformName}". Adding it to the project`);

        // Install from given URL if defined or using a plugin id. If spec
        // isn't a valid version or version range, assume it is the location to
        // install from.
        // CB-10761 If plugin spec is not specified, use plugin name
        let installFrom = platform.spec || platformName;
        if (platform.spec && semver.validRange(platform.spec, true)) {
            installFrom = platformName + '@' + platform.spec;
        }

        const cordovaPlatform = require('./platform');
        return cordovaPlatform('add', installFrom, opts);
    }

    function errCallback (error) {
        // CB-10921 emit a warning in case of error
        const msg = `Failed to restore platform "${platformName}". You might need to try adding it again. Error: ${error}`;
        process.exitCode = 1;
        events.emit('warn', msg);

        return Promise.reject(error);
    }

    // CB-9278 : Run `platform add` serially, one platform after another
    // Otherwise, we get a bug where the following line: https://github.com/apache/cordova-lib/blob/0b0dee5e403c2c6d4e7262b963babb9f532e7d27/cordova-lib/src/util/npm-helper.js#L39
    // gets executed simultaneously by each platform and leads to an exception being thrown
    return platformInfo.reduce(function (soFar, platform) {
        return soFar.then(() => restoreCallback(platform), errCallback);
    }, Promise.resolve());
}

// Returns a promise.
function installPluginsFromConfigXML (args) {
    events.emit('verbose', 'Checking for saved plugins that haven\'t been added to the project');

    const projectRoot = cordova_util.getProjectRoot();
    const pluginsRoot = path.join(projectRoot, 'plugins');
    const pkgJsonPath = path.join(projectRoot, 'package.json');
    const confXmlPath = cordova_util.projectConfig(projectRoot);

    let pkgJson = {};
    let indent = '  ';
    let newline = '\n';

    if (fs.existsSync(pkgJsonPath)) {
        const fileData = fs.readFileSync(pkgJsonPath, 'utf8');
        indent = detectIndent(fileData).indent;
        newline = detectNewline(fileData);
        pkgJson = JSON.parse(fileData);
    }

    pkgJson.dependencies = pkgJson.dependencies || {};
    pkgJson.devDependencies = pkgJson.devDependencies || {};
    pkgJson.cordova = pkgJson.cordova || {};
    pkgJson.cordova.plugins = pkgJson.cordova.plugins || {};

    const pkgPluginIDs = Object.keys(pkgJson.cordova.plugins);
    const pkgSpecs = Object.assign({}, pkgJson.dependencies, pkgJson.devDependencies);

    // Check for plugins listed in config.xml
    const cfg = new ConfigParser(confXmlPath);
    const cfgPluginIDs = cfg.getPluginIdList();

    cfgPluginIDs.forEach(plID => {
        // If package.json includes the plugin, we use that config
        // Otherwise, we need to add the plugin to package.json
        if (!pkgPluginIDs.includes(plID)) {
            events.emit('info', `Plugin '${plID}' found in config.xml... Migrating it to package.json`);

            const cfgPlugin = cfg.getPlugin(plID);

            // If config.xml has a spec for the plugin and package.json has not,
            // add the spec to devDependencies of package.json
            if (cfgPlugin.spec && !(plID in pkgSpecs)) {
                pkgJson.devDependencies[plID] = cfgPlugin.spec;
            }

            pkgJson.cordova.plugins[plID] = Object.assign({}, cfgPlugin.variables);
        }
    });

    // Now that plugins have been updated, re-fetch them from package.json
    const pluginIDs = Object.keys(pkgJson.cordova.plugins);

    if (pluginIDs.length !== pkgPluginIDs.length) {
        // We've modified package.json and need to save it
        writeFileAtomicSync(pkgJsonPath, stringifyPackage(pkgJson, indent, newline), { encoding: 'utf8' });
    }

    const specs = Object.assign({}, pkgJson.dependencies, pkgJson.devDependencies);

    const plugins = pluginIDs.map(plID => ({
        name: plID,
        spec: specs[plID],
        variables: pkgJson.cordova.plugins[plID] || {}
    }));

    let pluginName = '';

    function restoreCallback (pluginConfig) {
        pluginName = pluginConfig.name;

        const pluginPath = path.join(pluginsRoot, pluginName);
        if (fs.existsSync(pluginPath)) {
            // Plugin already exists
            return Promise.resolve();
        }

        events.emit('log', `Discovered plugin "${pluginName}". Adding it to the project`);

        // Install from given URL if defined or using a plugin id. If spec isn't a valid version or version range,
        // assume it is the location to install from.
        // CB-10761 If plugin spec is not specified, use plugin name
        let installFrom = pluginConfig.spec || pluginName;
        if (pluginConfig.spec && semver.validRange(pluginConfig.spec, true)) {
            installFrom = pluginName + '@' + pluginConfig.spec;
        }

        // Add feature preferences as CLI variables if have any
        const options = {
            cli_variables: pluginConfig.variables,
            searchpath: args.searchpath,
            save: args.save || false
        };

        const plugin = require('./plugin');
        return plugin('add', installFrom, options);
    }

    function errCallback (error) {
        // CB-10921 emit a warning in case of error
        const msg = `Failed to restore plugin "${pluginName}". You might need to try adding it again. Error: ${error}`;
        process.exitCode = 1;
        events.emit('warn', msg);
    }

    // CB-9560 : Run `plugin add` serially, one plugin after another
    // We need to wait for the plugin and its dependencies to be installed
    // before installing the next root plugin otherwise we can have common
    // plugin dependencies installed twice which throws a nasty error.
    return plugins.reduce(function (soFar, plugin) {
        return soFar.then(() => restoreCallback(plugin), errCallback);
    }, Promise.resolve());
}
