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

/*
A class for holidng the information currently stored in plugin.xml
It should also be able to answer questions like whether the plugin
is compatible with a given engine version.

TODO (kamrik): refactor this to not use sync functions and return promises.
*/

var path = require('path');
var fs = require('fs');
var xml_helpers = require('../util/xml-helpers');
var CordovaError = require('../CordovaError/CordovaError');

function PluginInfo (dirname) {
    var self = this;

    // METHODS
    // Defined inside the constructor to avoid the "this" binding problems.

    // <preference> tag
    // Example: <preference name="API_KEY" />
    // Used to require a variable to be specified via --variable when installing the plugin.
    // returns { key : default | null}
    self.getPreferences = getPreferences;
    function getPreferences (platform) {
        return _getTags(self._et, 'preference', platform, _parsePreference)
            .reduce(function (preferences, pref) {
                preferences[pref.preference] = pref.default;
                return preferences;
            }, {});
    }

    function _parsePreference (prefTag) {
        var name = prefTag.attrib.name.toUpperCase();
        var def = prefTag.attrib.default || null;
        return {preference: name, default: def};
    }

    // <asset>
    self.getAssets = getAssets;
    function getAssets (platform) {
        var assets = _getTags(self._et, 'asset', platform, _parseAsset);
        return assets;
    }

    function _parseAsset (tag) {
        var src = tag.attrib.src;
        var target = tag.attrib.target;

        if (!src || !target) {
            var msg =
                'Malformed <asset> tag. Both "src" and "target" attributes'
                + 'must be specified in\n'
                + self.filepath
                ;
            throw new Error(msg);
        }

        var asset = {
            itemType: 'asset',
            src: src,
            target: target
        };
        return asset;
    }

    // <dependency>
    // Example:
    // <dependency id="com.plugin.id"
    //     url="https://github.com/myuser/someplugin"
    //     commit="428931ada3891801"
    //     subdir="some/path/here" />
    self.getDependencies = getDependencies;
    function getDependencies (platform) {
        var deps = _getTags(
            self._et,
            'dependency',
            platform,
            _parseDependency
        );
        return deps;
    }

    function _parseDependency (tag) {
        var dep =
            { id: tag.attrib.id,
                version: tag.attrib.version || '',
                url: tag.attrib.url || '',
                subdir: tag.attrib.subdir || '',
                commit: tag.attrib.commit
            };

        dep.git_ref = dep.commit;

        if (!dep.id) {
            var msg =
                '<dependency> tag is missing id attribute in '
                + self.filepath
                ;
            throw new CordovaError(msg);
        }
        return dep;
    }

    // <config-file> tag
    self.getConfigFiles = getConfigFiles;
    function getConfigFiles (platform) {
        var configFiles = _getTags(self._et, 'config-file', platform, _parseConfigFile);
        return configFiles;
    }

    function _parseConfigFile (tag) {
        var configFile =
            { target: tag.attrib['target'],
                parent: tag.attrib['parent'],
                after: tag.attrib['after'],
                xmls: tag.getchildren(),
                // To support demuxing via versions
                versions: tag.attrib['versions'],
                deviceTarget: tag.attrib['device-target']
            };
        return configFile;
    }

    self.getEditConfigs = getEditConfigs;
    function getEditConfigs (platform) {
        var editConfigs = _getTags(self._et, 'edit-config', platform, _parseEditConfigs);
        return editConfigs;
    }

    function _parseEditConfigs (tag) {
        var editConfig =
            { file: tag.attrib['file'],
                target: tag.attrib['target'],
                mode: tag.attrib['mode'],
                xmls: tag.getchildren()
            };
        return editConfig;
    }

    // <info> tags, both global and within a <platform>
    // TODO (kamrik): Do we ever use <info> under <platform>? Example wanted.
    self.getInfo = getInfo;
    function getInfo (platform) {
        var infos = _getTags(
            self._et,
            'info',
            platform,
            function (elem) { return elem.text; }
        );
        // Filter out any undefined or empty strings.
        infos = infos.filter(Boolean);
        return infos;
    }

    // <source-file>
    // Examples:
    // <source-file src="src/ios/someLib.a" framework="true" />
    // <source-file src="src/ios/someLib.a" compiler-flags="-fno-objc-arc" />
    self.getSourceFiles = getSourceFiles;
    function getSourceFiles (platform) {
        var sourceFiles = _getTagsInPlatform(self._et, 'source-file', platform, _parseSourceFile);
        return sourceFiles;
    }

    function _parseSourceFile (tag) {
        return {
            itemType: 'source-file',
            src: tag.attrib.src,
            framework: isStrTrue(tag.attrib.framework),
            weak: isStrTrue(tag.attrib.weak),
            compilerFlags: tag.attrib['compiler-flags'],
            targetDir: tag.attrib['target-dir']
        };
    }

    // <header-file>
    // Example:
    // <header-file src="CDVFoo.h" />
    self.getHeaderFiles = getHeaderFiles;
    function getHeaderFiles (platform) {
        var headerFiles = _getTagsInPlatform(self._et, 'header-file', platform, function (tag) {
            return {
                itemType: 'header-file',
                src: tag.attrib.src,
                targetDir: tag.attrib['target-dir']
            };
        });
        return headerFiles;
    }

    // <resource-file>
    // Example:
    // <resource-file src="FooPluginStrings.xml" target="res/values/FooPluginStrings.xml" device-target="win" arch="x86" versions="&gt;=8.1" />
    self.getResourceFiles = getResourceFiles;
    function getResourceFiles (platform) {
        var resourceFiles = _getTagsInPlatform(self._et, 'resource-file', platform, function (tag) {
            return {
                itemType: 'resource-file',
                src: tag.attrib.src,
                target: tag.attrib.target,
                versions: tag.attrib.versions,
                deviceTarget: tag.attrib['device-target'],
                arch: tag.attrib.arch,
                reference: tag.attrib.reference
            };
        });
        return resourceFiles;
    }

    // <lib-file>
    // Example:
    // <lib-file src="src/BlackBerry10/native/device/libfoo.so" arch="device" />
    self.getLibFiles = getLibFiles;
    function getLibFiles (platform) {
        var libFiles = _getTagsInPlatform(self._et, 'lib-file', platform, function (tag) {
            return {
                itemType: 'lib-file',
                src: tag.attrib.src,
                arch: tag.attrib.arch,
                Include: tag.attrib.Include,
                versions: tag.attrib.versions,
                deviceTarget: tag.attrib['device-target'] || tag.attrib.target
            };
        });
        return libFiles;
    }

    // <hook>
    // Example:
    // <hook type="before_build" src="scripts/beforeBuild.js" />
    self.getHookScripts = getHookScripts;
    function getHookScripts (hook, platforms) {
        var scriptElements = self._et.findall('./hook');

        if (platforms) {
            platforms.forEach(function (platform) {
                scriptElements = scriptElements.concat(self._et.findall('./platform[@name="' + platform + '"]/hook'));
            });
        }

        function filterScriptByHookType (el) {
            return el.attrib.src && el.attrib.type && el.attrib.type.toLowerCase() === hook;
        }

        return scriptElements.filter(filterScriptByHookType);
    }

    self.getJsModules = getJsModules;
    function getJsModules (platform) {
        var modules = _getTags(self._et, 'js-module', platform, _parseJsModule);
        return modules;
    }

    function _parseJsModule (tag) {
        var ret = {
            itemType: 'js-module',
            name: tag.attrib.name,
            src: tag.attrib.src,
            clobbers: tag.findall('clobbers').map(function (tag) { return { target: tag.attrib.target }; }),
            merges: tag.findall('merges').map(function (tag) { return { target: tag.attrib.target }; }),
            runs: tag.findall('runs').length > 0
        };

        return ret;
    }

    self.getEngines = function () {
        return self._et.findall('engines/engine').map(function (n) {
            return {
                name: n.attrib.name,
                version: n.attrib.version,
                platform: n.attrib.platform,
                scriptSrc: n.attrib.scriptSrc
            };
        });
    };

    self.getPlatforms = function () {
        return self._et.findall('platform').map(function (n) {
            return { name: n.attrib.name };
        });
    };

    self.getPlatformsArray = function () {
        return self._et.findall('platform').map(function (n) {
            return n.attrib.name;
        });
    };

    self.getFrameworks = function (platform, options) {
        return _getTags(self._et, 'framework', platform, function (el) {
            var src = el.attrib.src;
            if (options) {
                var vars = options.cli_variables || {};

                if (Object.keys(vars).length === 0) {
                    // get variable defaults from plugin.xml for removal
                    vars = self.getPreferences(platform);
                }
                var regExp;
                // Iterate over plugin variables.
                // Replace them in framework src if they exist
                Object.keys(vars).forEach(function (name) {
                    if (vars[name]) {
                        regExp = new RegExp('\\$' + name, 'g');
                        src = src.replace(regExp, vars[name]);
                    }
                });
            }
            var ret = {
                itemType: 'framework',
                type: el.attrib.type,
                parent: el.attrib.parent,
                custom: isStrTrue(el.attrib.custom),
                embed: isStrTrue(el.attrib.embed),
                src: src,
                spec: el.attrib.spec,
                weak: isStrTrue(el.attrib.weak),
                versions: el.attrib.versions,
                targetDir: el.attrib['target-dir'],
                deviceTarget: el.attrib['device-target'] || el.attrib.target,
                arch: el.attrib.arch,
                implementation: el.attrib.implementation
            };
            return ret;
        });
    };

    self.getFilesAndFrameworks = getFilesAndFrameworks;
    function getFilesAndFrameworks (platform, options) {
        // Please avoid changing the order of the calls below, files will be
        // installed in this order.
        var items = [].concat(
            self.getSourceFiles(platform),
            self.getHeaderFiles(platform),
            self.getResourceFiles(platform),
            self.getFrameworks(platform, options),
            self.getLibFiles(platform)
        );
        return items;
    }
    /// // End of PluginInfo methods /////

    /// // PluginInfo Constructor logic  /////
    self.filepath = path.join(dirname, 'plugin.xml');
    if (!fs.existsSync(self.filepath)) {
        throw new CordovaError('Cannot find plugin.xml for plugin "' + path.basename(dirname) + '". Please try adding it again.');
    }

    self.dir = dirname;
    var et = self._et = xml_helpers.parseElementtreeSync(self.filepath);
    var pelem = et.getroot();
    self.id = pelem.attrib.id;
    self.version = pelem.attrib.version;

    // Optional fields
    self.name = pelem.findtext('name');
    self.description = pelem.findtext('description');
    self.license = pelem.findtext('license');
    self.repo = pelem.findtext('repo');
    self.issue = pelem.findtext('issue');
    self.keywords = pelem.findtext('keywords');
    self.info = pelem.findtext('info');
    if (self.keywords) {
        self.keywords = self.keywords.split(',').map(function (s) { return s.trim(); });
    }
    self.getKeywordsAndPlatforms = function () {
        var ret = self.keywords || [];
        return ret.concat('ecosystem:cordova').concat(addCordova(self.getPlatformsArray()));
    };
} // End of PluginInfo constructor.

// Helper function used to prefix every element of an array with cordova-
// Useful when we want to modify platforms to be cordova-platform
function addCordova (someArray) {
    var newArray = someArray.map(function (element) {
        return 'cordova-' + element;
    });
    return newArray;
}

// Helper function used by most of the getSomething methods of PluginInfo.
// Get all elements of a given name. Both in root and in platform sections
// for the given platform. If transform is given and is a function, it is
// applied to each element.
function _getTags (pelem, tag, platform, transform) {
    var platformTag = pelem.find('./platform[@name="' + platform + '"]');
    var tagsInRoot = pelem.findall(tag);
    tagsInRoot = tagsInRoot || [];
    var tagsInPlatform = platformTag ? platformTag.findall(tag) : [];
    var tags = tagsInRoot.concat(tagsInPlatform);
    if (typeof transform === 'function') {
        tags = tags.map(transform);
    }
    return tags;
}

// Same as _getTags() but only looks inside a platform section.
function _getTagsInPlatform (pelem, tag, platform, transform) {
    var platformTag = pelem.find('./platform[@name="' + platform + '"]');
    var tags = platformTag ? platformTag.findall(tag) : [];
    if (typeof transform === 'function') {
        tags = tags.map(transform);
    }
    return tags;
}

// Check if x is a string 'true'.
function isStrTrue (x) {
    return String(x).toLowerCase() === 'true';
}

module.exports = PluginInfo;
// Backwards compat:
PluginInfo.PluginInfo = PluginInfo;
PluginInfo.loadPluginsDir = function (dir) {
    var PluginInfoProvider = require('./PluginInfoProvider');
    return new PluginInfoProvider().getAllWithinSearchPath(dir);
};
