/**
    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-extra');
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].startsWith('xmlns:') &&
            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 || '';
}

function removeChildren (el, selector) {
    const matches = el.findall(selector);
    matches.forEach(child => el.remove(child));
}

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

    packageName: function () {
        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'));
    },
    setPlatformPreference: function (name, platform, value) {
        const platformEl = this.doc.find('./platform[@name="' + platform + '"]');
        if (!platformEl) {
            throw new CordovaError('platform does not exist (received platform: ' + platform + ')');
        }
        const elems = this.doc.findall('./platform[@name="' + platform + '"]/preference');
        let pref = elems.filter(function (elem) {
            return elem.attrib.name.toLowerCase() === name.toLowerCase();
        }).pop();

        if (!pref) {
            pref = new et.Element('preference');
            pref.attrib.name = name;
            platformEl.append(pref);
        }
        pref.attrib.value = value;
    },
    getPreference: function (name, platform) {

        var platformPreference = '';

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

        return platformPreference || this.getGlobalPreference(name);

    },
    setPreference: function (name, platform, value) {
        if (!value) {
            value = platform;
            platform = undefined;
        }

        if (platform) {
            this.setPlatformPreference(name, platform, value);
        } else {
            this.setGlobalPreference(name, value);
        }
    },
    /**
     * 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;
            res.background = elt.attrib.background || undefined;
            res.foreground = elt.attrib.foreground || 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) return;
        const root = this.doc.getroot();
        removeChildren(root, `./plugin/[@name="${id}"]`);
        removeChildren(root, `./feature/param[@name="id"][@value="${id}"]/..`);
    },

    // 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) {
        removeChildren(this.doc.getroot(), `./engine/[@name="${name}"]`);
    },
    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_edit_configs = this.doc.findall('./platform[@name="' + platform + '"]/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_config_files = this.doc.findall('./platform[@name="' + platform + '"]/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'],
                    id: 'config.xml'
                };
            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;
