/*
    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.
*/

// copyright (c) 2013 Andrew Lunny, Adobe Systems

const pTry = require('p-try');
const pEachSeries = require('p-each-series');
const { plugman } = require('cordova-lib');

module.exports = {
    install (cli_opts) {
        assertRequiredOptions(cli_opts, ['platform', 'project', 'plugin']);

        var opts = {
            subdir: '.',
            cli_variables: expandCliVariables(cli_opts.variable),
            save: cli_opts.save || false,
            www_dir: cli_opts.www,
            searchpath: cli_opts.searchpath,
            link: cli_opts.link,
            projectRoot: cli_opts.project,
            force: cli_opts.force || false,
            nohooks: cli_opts.nohooks || false
        };

        return pEachSeries(cli_opts.plugin, pluginSrc =>
            plugman.install(cli_opts.platform, cli_opts.project, pluginSrc, cli_opts.plugins_dir, opts)
        );
    },

    uninstall (cli_opts) {
        assertRequiredOptions(cli_opts, ['platform', 'project', 'plugin']);

        var opts = {
            www_dir: cli_opts.www,
            save: cli_opts.save || false,
            projectRoot: cli_opts.project
        };

        return pEachSeries(cli_opts.plugin, pluginSrc =>
            plugman.uninstall(cli_opts.platform, cli_opts.project, pluginSrc, cli_opts.plugins_dir, opts)
        );
    },

    create (cli_opts) {
        assertRequiredOptions(cli_opts, ['name', 'plugin_id', 'plugin_version']);

        const cli_variables = expandCliVariables(cli_opts.variable);
        return plugman.create(cli_opts.name, cli_opts.plugin_id, cli_opts.plugin_version, cli_opts.path || '.', cli_variables);
    },

    platform (cli_opts) {
        assertRequiredOptions(cli_opts, ['platform_name']);
        var operation = cli_opts.argv.remain[ 0 ] || '';
        if (operation !== 'add' && operation !== 'remove') {
            throw new Error(`Operation must be either 'add' or 'remove' but was '${operation}'`);
        }

        return plugman.platform({ operation: operation, platform_name: cli_opts.platform_name });
    },

    createpackagejson (cli_opts) {
        var plugin_path = cli_opts.argv.remain[0];
        if (!plugin_path) {
            throw new Error(`Missing required path to plugin`);
        }
        return plugman.createpackagejson(plugin_path);
    }
};

// Until we can declare all above functions async, wrap them all with pTry
// to turn all thrown errors into rejections
for (const key in module.exports) {
    const fn = module.exports[key];
    module.exports[key] = (...args) => pTry(fn, ...args);
}

function assertRequiredOptions (options, requiredKeys) {
    for (const key of requiredKeys) {
        if (!options[key]) throw new Error(`Missing required option --${key}`);
    }
}

function expandCliVariables (cliVarList) {
    return (cliVarList || []).reduce((cli_variables, variable) => {
        var tokens = variable.split('=');
        var key = tokens.shift().toUpperCase();
        if (/^[\w-_]+$/.test(key)) cli_variables[key] = tokens.join('=');
        return cli_variables;
    }, {});
}
