/**
    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 et = require('elementtree');
var xml = require('../util/xml-helpers');
var CordovaError = require('../CordovaError/CordovaError');
var fs = require('fs');
var events = require('../events');

/** Wraps a config.xml file */
function ConfigParser (path) {
    this.path = path;
    try {
        this.doc = xml.parseElementtreeSync(path);
        this.cdvNamespacePrefix = getCordovaNamespacePrefix(this.doc);
        et.register_namespace(this.cdvNamespacePrefix, 'http://cordova.apache.org/ns/1.0');
    } catch (e) {
        events.emit('error', 'Parsing ' + path + ' failed');
        throw e;
    }
    var r = this.doc.getroot();
    if (r.tag !== 'widget') {
        throw new CordovaError(path + ' has incorrect root node name (expected "widget", was "' + r.tag + '")');
    }
}

function getNodeTextSafe (el) {
    return el && el.text && el.text.trim();
}

function findOrCreate (doc, name) {
    var ret = doc.find(name);
    if (!ret) {
        ret = new et.Element(name);
        doc.getroot().append(ret);
    }
    return ret;
}

function getCordovaNamespacePrefix (doc) {
    var rootAtribs = Object.getOwnPropertyNames(doc.getroot().attrib);
    var prefix = 'cdv';
    for (var j = 0; j < rootAtribs.length; j++) {
        if (rootAtribs[j].indexOf('xmlns:') === 0 &&
            doc.getroot().attrib[rootAtribs[j]] === 'http://cordova.apache.org/ns/1.0') {
            var strings = rootAtribs[j].split(':');
            prefix = strings[1];
            break;
        }
    }
    return prefix;
}

/**
 * Finds the value of an element's attribute
 * @param  {String} attributeName Name of the attribute to search for
 * @param  {Array}  elems         An array of ElementTree nodes
 * @return {String}
 */
function findElementAttributeValue (attributeName, elems) {

    elems = Array.isArray(elems) ? elems : [ elems ];

    var value = elems.filter(function (elem) {
        return elem.attrib.name.toLowerCase() === attributeName.toLowerCase();
    }).map(function (filteredElems) {
        return filteredElems.attrib.value;
    }).pop();

    return value || '';
}

ConfigParser.prototype = {
    getAttribute: function (attr) {
        return this.doc.getroot().attrib[attr];
    },

    packageName: function (id) {
        return this.getAttribute('id');
    },
    setPackageName: function (id) {
        this.doc.getroot().attrib['id'] = id;
    },
    android_packageName: function () {
        return this.getAttribute('android-packageName');
    },
    android_activityName: function () {
        return this.getAttribute('android-activityName');
    },
    ios_CFBundleIdentifier: function () {
        return this.getAttribute('ios-CFBundleIdentifier');
    },
    name: function () {
        return getNodeTextSafe(this.doc.find('name'));
    },
    setName: function (name) {
        var el = findOrCreate(this.doc, 'name');
        el.text = name;
    },
    shortName: function () {
        return this.doc.find('name').attrib['short'] || this.name();
    },
    setShortName: function (shortname) {
        var el = findOrCreate(this.doc, 'name');
        if (!el.text) {
            el.text = shortname;
        }
        el.attrib['short'] = shortname;
    },
    description: function () {
        return getNodeTextSafe(this.doc.find('description'));
    },
    setDescription: function (text) {
        var el = findOrCreate(this.doc, 'description');
        el.text = text;
    },
    version: function () {
        return this.getAttribute('version');
    },
    windows_packageVersion: function () {
        return this.getAttribute('windows-packageVersion');
    },
    android_versionCode: function () {
        return this.getAttribute('android-versionCode');
    },
    ios_CFBundleVersion: function () {
        return this.getAttribute('ios-CFBundleVersion');
    },
    setVersion: function (value) {
        this.doc.getroot().attrib['version'] = value;
    },
    author: function () {
        return getNodeTextSafe(this.doc.find('author'));
    },
    getGlobalPreference: function (name) {
        return findElementAttributeValue(name, this.doc.findall('preference'));
    },
    setGlobalPreference: function (name, value) {
        var pref = this.doc.find('preference[@name="' + name + '"]');
        if (!pref) {
            pref = new et.Element('preference');
            pref.attrib.name = name;
            this.doc.getroot().append(pref);
        }
        pref.attrib.value = value;
    },
    getPlatformPreference: function (name, platform) {
        return findElementAttributeValue(name, this.doc.findall('platform[@name=\'' + platform + '\']/preference'));
    },
    getPreference: function (name, platform) {

        var platformPreference = '';

        if (platform) {
            platformPreference = this.getPlatformPreference(name, platform);
        }

        return platformPreference || this.getGlobalPreference(name);

    },
    /**
     * Returns all resources for the platform specified.
     * @param  {String} platform     The platform.
     * @param {string}  resourceName Type of static resources to return.
     *                               "icon" and "splash" currently supported.
     * @return {Array}               Resources for the platform specified.
     */
    getStaticResources: function (platform, resourceName) {
        var ret = [];
        var staticResources = [];
        if (platform) { // platform specific icons
            this.doc.findall('platform[@name=\'' + platform + '\']/' + resourceName).forEach(function (elt) {
                elt.platform = platform; // mark as platform specific resource
                staticResources.push(elt);
            });
        }
        // root level resources
        staticResources = staticResources.concat(this.doc.findall(resourceName));
        // parse resource elements
        var that = this;
        staticResources.forEach(function (elt) {
            var res = {};
            res.src = elt.attrib.src;
            res.target = elt.attrib.target || undefined;
            res.density = elt.attrib['density'] || elt.attrib[that.cdvNamespacePrefix + ':density'] || elt.attrib['gap:density'];
            res.platform = elt.platform || null; // null means icon represents default icon (shared between platforms)
            res.width = +elt.attrib.width || undefined;
            res.height = +elt.attrib.height || undefined;

            // default icon
            if (!res.width && !res.height && !res.density) {
                ret.defaultResource = res;
            }
            ret.push(res);
        });

        /**
         * Returns resource with specified width and/or height.
         * @param  {number} width Width of resource.
         * @param  {number} height Height of resource.
         * @return {Resource} Resource object or null if not found.
         */
        ret.getBySize = function (width, height) {
            return ret.filter(function (res) {
                if (!res.width && !res.height) {
                    return false;
                }
                return ((!res.width || (width === res.width)) &&
                    (!res.height || (height === res.height)));
            })[0] || null;
        };

        /**
         * Returns resource with specified density.
         * @param  {string} density Density of resource.
         * @return {Resource}       Resource object or null if not found.
         */
        ret.getByDensity = function (density) {
            return ret.filter(function (res) {
                return res.density === density;
            })[0] || null;
        };

        /** Returns default icons */
        ret.getDefault = function () {
            return ret.defaultResource;
        };

        return ret;
    },

    /**
     * Returns all icons for specific platform.
     * @param  {string} platform Platform name
     * @return {Resource[]}      Array of icon objects.
     */
    getIcons: function (platform) {
        return this.getStaticResources(platform, 'icon');
    },

    /**
     * Returns all splash images for specific platform.
     * @param  {string} platform Platform name
     * @return {Resource[]}      Array of Splash objects.
     */
    getSplashScreens: function (platform) {
        return this.getStaticResources(platform, 'splash');
    },

    /**
     * Returns all resource-files for a specific platform.
     * @param  {string} platform Platform name
     * @param  {boolean} includeGlobal Whether to return resource-files at the
     *                                 root level.
     * @return {Resource[]}      Array of resource file objects.
     */
    getFileResources: function (platform, includeGlobal) {
        var fileResources = [];

        if (platform) { // platform specific resources
            fileResources = this.doc.findall('platform[@name=\'' + platform + '\']/resource-file').map(function (tag) {
                return {
                    platform: platform,
                    src: tag.attrib.src,
                    target: tag.attrib.target,
                    versions: tag.attrib.versions,
                    deviceTarget: tag.attrib['device-target'],
                    arch: tag.attrib.arch
                };
            });
        }

        if (includeGlobal) {
            this.doc.findall('resource-file').forEach(function (tag) {
                fileResources.push({
                    platform: platform || null,
                    src: tag.attrib.src,
                    target: tag.attrib.target,
                    versions: tag.attrib.versions,
                    deviceTarget: tag.attrib['device-target'],
                    arch: tag.attrib.arch
                });
            });
        }

        return fileResources;
    },

    /**
     * Returns all hook scripts for the hook type specified.
     * @param  {String} hook     The hook type.
     * @param {Array}  platforms Platforms to look for scripts into (root scripts will be included as well).
     * @return {Array}               Script elements.
     */
    getHookScripts: function (hook, platforms) {
        var self = this;
        var scriptElements = self.doc.findall('./hook');

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

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

        return scriptElements.filter(filterScriptByHookType);
    },
    /**
    * Returns a list of plugin (IDs).
    *
    * This function also returns any plugin's that
    * were defined using the legacy <feature> tags.
    * @return {string[]} Array of plugin IDs
    */
    getPluginIdList: function () {
        var plugins = this.doc.findall('plugin');
        var result = plugins.map(function (plugin) {
            return plugin.attrib.name;
        });
        var features = this.doc.findall('feature');
        features.forEach(function (element) {
            var idTag = element.find('./param[@name="id"]');
            if (idTag) {
                result.push(idTag.attrib.value);
            }
        });
        return result;
    },
    getPlugins: function () {
        return this.getPluginIdList().map(function (pluginId) {
            return this.getPlugin(pluginId);
        }, this);
    },
    /**
     * Adds a plugin element. Does not check for duplicates.
     * @name addPlugin
     * @function
     * @param {object} attributes name and spec are supported
     * @param {Array|object} variables name, value or arbitary object
     */
    addPlugin: function (attributes, variables) {
        if (!attributes && !attributes.name) return;
        var el = new et.Element('plugin');
        el.attrib.name = attributes.name;
        if (attributes.spec) {
            el.attrib.spec = attributes.spec;
        }

        // support arbitrary object as variables source
        if (variables && typeof variables === 'object' && !Array.isArray(variables)) {
            variables = Object.keys(variables)
                .map(function (variableName) {
                    return {name: variableName, value: variables[variableName]};
                });
        }

        if (variables) {
            variables.forEach(function (variable) {
                el.append(new et.Element('variable', { name: variable.name, value: variable.value }));
            });
        }
        this.doc.getroot().append(el);
    },
    /**
     * Retrives the plugin with the given id or null if not found.
     *
     * This function also returns any plugin's that
     * were defined using the legacy <feature> tags.
     * @name getPlugin
     * @function
     * @param {String} id
     * @returns {object} plugin including any variables
     */
    getPlugin: function (id) {
        if (!id) {
            return undefined;
        }
        var pluginElement = this.doc.find('./plugin/[@name="' + id + '"]');
        if (pluginElement === null) {
            var legacyFeature = this.doc.find('./feature/param[@name="id"][@value="' + id + '"]/..');
            if (legacyFeature) {
                events.emit('log', 'Found deprecated feature entry for ' + id + ' in config.xml.');
                return featureToPlugin(legacyFeature);
            }
            return undefined;
        }
        var plugin = {};

        plugin.name = pluginElement.attrib.name;
        plugin.spec = pluginElement.attrib.spec || pluginElement.attrib.src || pluginElement.attrib.version;
        plugin.variables = {};
        var variableElements = pluginElement.findall('variable');
        variableElements.forEach(function (varElement) {
            var name = varElement.attrib.name;
            var value = varElement.attrib.value;
            if (name) {
                plugin.variables[name] = value;
            }
        });
        return plugin;
    },
    /**
     * Remove the plugin entry with give name (id).
     *
     * This function also operates on any plugin's that
     * were defined using the legacy <feature> tags.
     * @name removePlugin
     * @function
     * @param id name of the plugin
     */
    removePlugin: function (id) {
        if (id) {
            var plugins = this.doc.findall('./plugin/[@name="' + id + '"]')
                .concat(this.doc.findall('./feature/param[@name="id"][@value="' + id + '"]/..'));
            var children = this.doc.getroot().getchildren();
            plugins.forEach(function (plugin) {
                var idx = children.indexOf(plugin);
                if (idx > -1) {
                    children.splice(idx, 1);
                }
            });
        }
    },

    // Add any element to the root
    addElement: function (name, attributes) {
        var el = et.Element(name);
        for (var a in attributes) {
            el.attrib[a] = attributes[a];
        }
        this.doc.getroot().append(el);
    },

    /**
     * Adds an engine. Does not check for duplicates.
     * @param  {String} name the engine name
     * @param  {String} spec engine source location or version (optional)
     */
    addEngine: function (name, spec) {
        if (!name) return;
        var el = et.Element('engine');
        el.attrib.name = name;
        if (spec) {
            el.attrib.spec = spec;
        }
        this.doc.getroot().append(el);
    },
    /**
     * Removes all the engines with given name
     * @param  {String} name the engine name.
     */
    removeEngine: function (name) {
        var engines = this.doc.findall('./engine/[@name="' + name + '"]');
        for (var i = 0; i < engines.length; i++) {
            var children = this.doc.getroot().getchildren();
            var idx = children.indexOf(engines[i]);
            if (idx > -1) {
                children.splice(idx, 1);
            }
        }
    },
    getEngines: function () {
        var engines = this.doc.findall('./engine');
        return engines.map(function (engine) {
            var spec = engine.attrib.spec || engine.attrib.version;
            return {
                'name': engine.attrib.name,
                'spec': spec || null
            };
        });
    },
    /* Get all the access tags */
    getAccesses: function () {
        var accesses = this.doc.findall('./access');
        return accesses.map(function (access) {
            var minimum_tls_version = access.attrib['minimum-tls-version']; /* String */
            var requires_forward_secrecy = access.attrib['requires-forward-secrecy']; /* Boolean */
            var requires_certificate_transparency = access.attrib['requires-certificate-transparency']; /* Boolean */
            var allows_arbitrary_loads_in_web_content = access.attrib['allows-arbitrary-loads-in-web-content']; /* Boolean */
            var allows_arbitrary_loads_in_media = access.attrib['allows-arbitrary-loads-in-media']; /* Boolean (DEPRECATED) */
            var allows_arbitrary_loads_for_media = access.attrib['allows-arbitrary-loads-for-media']; /* Boolean */
            var allows_local_networking = access.attrib['allows-local-networking']; /* Boolean */

            return {
                'origin': access.attrib.origin,
                'minimum_tls_version': minimum_tls_version,
                'requires_forward_secrecy': requires_forward_secrecy,
                'requires_certificate_transparency': requires_certificate_transparency,
                'allows_arbitrary_loads_in_web_content': allows_arbitrary_loads_in_web_content,
                'allows_arbitrary_loads_in_media': allows_arbitrary_loads_in_media,
                'allows_arbitrary_loads_for_media': allows_arbitrary_loads_for_media,
                'allows_local_networking': allows_local_networking
            };
        });
    },
    /* Get all the allow-navigation tags */
    getAllowNavigations: function () {
        var allow_navigations = this.doc.findall('./allow-navigation');
        return allow_navigations.map(function (allow_navigation) {
            var minimum_tls_version = allow_navigation.attrib['minimum-tls-version']; /* String */
            var requires_forward_secrecy = allow_navigation.attrib['requires-forward-secrecy']; /* Boolean */
            var requires_certificate_transparency = allow_navigation.attrib['requires-certificate-transparency']; /* Boolean */

            return {
                'href': allow_navigation.attrib.href,
                'minimum_tls_version': minimum_tls_version,
                'requires_forward_secrecy': requires_forward_secrecy,
                'requires_certificate_transparency': requires_certificate_transparency
            };
        });
    },
    /* Get all the allow-intent tags */
    getAllowIntents: function () {
        var allow_intents = this.doc.findall('./allow-intent');
        return allow_intents.map(function (allow_intent) {
            return {
                'href': allow_intent.attrib.href
            };
        });
    },
    /* Get all edit-config tags */
    getEditConfigs: function (platform) {
        var platform_tag = this.doc.find('./platform[@name="' + platform + '"]');
        var platform_edit_configs = platform_tag ? platform_tag.findall('edit-config') : [];

        var edit_configs = this.doc.findall('edit-config').concat(platform_edit_configs);

        return edit_configs.map(function (tag) {
            var editConfig =
                {
                    file: tag.attrib['file'],
                    target: tag.attrib['target'],
                    mode: tag.attrib['mode'],
                    id: 'config.xml',
                    xmls: tag.getchildren()
                };
            return editConfig;
        });
    },

    /* Get all config-file tags */
    getConfigFiles: function (platform) {
        var platform_tag = this.doc.find('./platform[@name="' + platform + '"]');
        var platform_config_files = platform_tag ? platform_tag.findall('config-file') : [];

        var config_files = this.doc.findall('config-file').concat(platform_config_files);

        return config_files.map(function (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;
        });
    },

    write: function () {
        fs.writeFileSync(this.path, this.doc.write({indent: 4}), 'utf-8');
    }
};

function featureToPlugin (featureElement) {
    var plugin = {};
    plugin.variables = [];
    var pluginVersion,
        pluginSrc;

    var nodes = featureElement.findall('param');
    nodes.forEach(function (element) {
        var n = element.attrib.name;
        var v = element.attrib.value;
        if (n === 'id') {
            plugin.name = v;
        } else if (n === 'version') {
            pluginVersion = v;
        } else if (n === 'url' || n === 'installPath') {
            pluginSrc = v;
        } else {
            plugin.variables[n] = v;
        }
    });

    var spec = pluginSrc || pluginVersion;
    if (spec) {
        plugin.spec = spec;
    }

    return plugin;
}
module.exports = ConfigParser;
