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

var Q = require('q');
var fs = require('fs-extra');
var path = require('path');

var ActionStack = require('./ActionStack');
var PlatformJson = require('./PlatformJson');
var CordovaError = require('./CordovaError/CordovaError');
var PlatformMunger = require('./ConfigChanges/ConfigChanges').PlatformMunger;
var PluginInfoProvider = require('./PluginInfo/PluginInfoProvider');

/**
 * @constructor
 * @class PluginManager
 * Represents an entity for adding/removing plugins for platforms
 *
 * @param {String} platform Platform name
 * @param {Object} locations - Platform files and directories
 * @param {IDEProject} ideProject The IDE project to add/remove plugin changes to/from
 */
function PluginManager (platform, locations, ideProject) {
    this.platform = platform;
    this.locations = locations;
    this.project = ideProject;

    var platformJson = PlatformJson.load(locations.root, platform);
    this.munger = new PlatformMunger(platform, locations.root, platformJson, new PluginInfoProvider());
}

/**
 * @constructs PluginManager
 * A convenience shortcut to new PluginManager(...)
 *
 * @param {String} platform Platform name
 * @param {Object} locations - Platform files and directories
 * @param {IDEProject} ideProject The IDE project to add/remove plugin changes to/from
 * @returns new PluginManager instance
 */
PluginManager.get = function (platform, locations, ideProject) {
    return new PluginManager(platform, locations, ideProject);
};

PluginManager.INSTALL = 'install';
PluginManager.UNINSTALL = 'uninstall';

module.exports = PluginManager;

/**
 * Describes and implements common plugin installation/uninstallation routine. The flow is the following:
 *  * Validate and set defaults for options. Note that options are empty by default. Everything
 *    needed for platform IDE project must be passed from outside. Plugin variables (which
 *    are the part of the options) also must be already populated with 'PACKAGE_NAME' variable.
 *  * Collect all plugin's native and web files, get installers/uninstallers and process
 *    all these via ActionStack.
 *  * Save the IDE project, so the changes made by installers are persisted.
 *  * Generate config changes munge for plugin and apply it to all required files
 *  * Generate metadata for plugin and plugin modules and save it to 'cordova_plugins.js'
 *
 * @param {PluginInfo} plugin A PluginInfo structure representing plugin to install
 * @param {Object} [options={}] An installation options. It is expected but is not necessary
 *   that options would contain 'variables' inner object with 'PACKAGE_NAME' field set by caller.
 *
 * @returns {Promise} Returns a Q promise, either resolved in case of success, rejected otherwise.
 */
PluginManager.prototype.doOperation = function (operation, plugin, options) {
    if (operation !== PluginManager.INSTALL && operation !== PluginManager.UNINSTALL) { return Q.reject(new CordovaError('The parameter is incorrect. The opeation must be either "add" or "remove"')); }

    if (!plugin || plugin.constructor.name !== 'PluginInfo') { return Q.reject(new CordovaError('The parameter is incorrect. The first parameter should be a PluginInfo instance')); }

    // Set default to empty object to play safe when accesing properties
    options = options || {};

    var self = this;
    var actions = new ActionStack();

    // gather all files need to be handled during operation ...
    plugin.getFilesAndFrameworks(this.platform, options)
        .concat(plugin.getAssets(this.platform))
        .concat(plugin.getJsModules(this.platform))
        // ... put them into stack ...
        .forEach(function (item) {
            var installer = self.project.getInstaller(item.itemType);
            var uninstaller = self.project.getUninstaller(item.itemType);
            var actionArgs = [item, plugin, self.project, options];

            var action;
            if (operation === PluginManager.INSTALL) {
                action = actions.createAction.apply(actions, [installer, actionArgs, uninstaller, actionArgs]); /* eslint no-useless-call: 0 */
            } else /* op === PluginManager.UNINSTALL */{
                action = actions.createAction.apply(actions, [uninstaller, actionArgs, installer, actionArgs]); /* eslint no-useless-call: 0 */
            }
            actions.push(action);
        });

    // ... and run through the action stack
    return actions.process(this.platform)
        .then(function () {
            if (self.project.write) {
                self.project.write();
            }

            if (operation === PluginManager.INSTALL) {
                // Ignore passed `is_top_level` option since platform itself doesn't know
                // anything about managing dependencies - it's responsibility of caller.
                self.munger.add_plugin_changes(plugin, options.variables, /* is_top_level= */true, /* should_increment= */true, options.force);
                self.munger.platformJson.addPluginMetadata(plugin);
            } else {
                self.munger.remove_plugin_changes(plugin, /* is_top_level= */true);
                self.munger.platformJson.removePluginMetadata(plugin);
            }

            // Save everything (munge and plugin/modules metadata)
            self.munger.save_all();

            var metadata = self.munger.platformJson.generateMetadata();
            fs.writeFileSync(path.join(self.locations.www, 'cordova_plugins.js'), metadata, 'utf-8');

            // CB-11022 save plugin metadata to both www and platform_www if options.usePlatformWww is specified
            if (options.usePlatformWww) {
                fs.writeFileSync(path.join(self.locations.platformWww, 'cordova_plugins.js'), metadata, 'utf-8');
            }
        });
};

PluginManager.prototype.addPlugin = function (plugin, installOptions) {
    return this.doOperation(PluginManager.INSTALL, plugin, installOptions);
};

PluginManager.prototype.removePlugin = function (plugin, uninstallOptions) {
    return this.doOperation(PluginManager.UNINSTALL, plugin, uninstallOptions);
};
