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

/**
 * contains XML utility functions, some of which are specific to elementtree
 */

var fs = require('fs-extra');
var path = require('path');
var _ = require('underscore');
var et = require('elementtree');
var stripBom = require('strip-bom');

/* eslint-disable no-useless-escape */
var ROOT = /^\/([^\/]*)/;
var ABSOLUTE = /^\/([^\/]*)\/(.*)/;
/* eslint-enable no-useless-escape */

module.exports = {
    // compare two et.XML nodes, see if they match
    // compares tagName, text, attributes and children (recursively)
    equalNodes: function (one, two) {
        if (one.tag !== two.tag) {
            return false;
        } else if (one.text.trim() !== two.text.trim()) {
            return false;
        } else if (one._children.length !== two._children.length) {
            return false;
        }

        if (!attribMatch(one, two)) return false;

        for (var i = 0; i < one._children.length; i++) {
            if (!module.exports.equalNodes(one._children[i], two._children[i])) {
                return false;
            }
        }

        return true;
    },

    // adds node to doc at selector, creating parent if it doesn't exist
    graftXML: function (doc, nodes, selector, after) {
        var parent = module.exports.resolveParent(doc, selector);
        if (!parent) {
            // Try to create the parent recursively if necessary
            try {
                var parentToCreate = et.XML('<' + path.basename(selector) + '/>');
                var parentSelector = path.dirname(selector);

                this.graftXML(doc, [parentToCreate], parentSelector);
            } catch (e) {
                return false;
            }
            parent = module.exports.resolveParent(doc, selector);
            if (!parent) return false;
        }

        nodes.forEach(function (node) {
            // check if child is unique first
            if (uniqueChild(node, parent)) {
                var children = parent.getchildren();
                var insertIdx = after ? findInsertIdx(children, after) : children.length;

                // TODO: replace with parent.insert after the bug in ElementTree is fixed
                parent.getchildren().splice(insertIdx, 0, node);
            }
        });

        return true;
    },

    // adds new attributes to doc at selector
    // Will only merge if attribute has not been modified already or --force is used
    graftXMLMerge: function (doc, nodes, selector, xml) {
        var target = module.exports.resolveParent(doc, selector);
        if (!target) return false;

        // saves the attributes of the original xml before making changes
        xml.oldAttrib = _.extend({}, target.attrib);

        nodes.forEach(function (node) {
            var attributes = node.attrib;
            for (var attribute in attributes) {
                target.attrib[attribute] = node.attrib[attribute];
            }
        });

        return true;
    },

    // overwrite all attributes to doc at selector with new attributes
    // Will only overwrite if attribute has not been modified already or --force is used
    graftXMLOverwrite: function (doc, nodes, selector, xml) {
        var target = module.exports.resolveParent(doc, selector);
        if (!target) return false;

        // saves the attributes of the original xml before making changes
        xml.oldAttrib = _.extend({}, target.attrib);

        // remove old attributes from target
        var targetAttributes = target.attrib;
        for (var targetAttribute in targetAttributes) {
            delete targetAttributes[targetAttribute];
        }

        // add new attributes to target
        nodes.forEach(function (node) {
            var attributes = node.attrib;
            for (var attribute in attributes) {
                target.attrib[attribute] = node.attrib[attribute];
            }
        });

        return true;
    },

    // removes node from doc at selector
    pruneXML: function (doc, nodes, selector) {
        var parent = module.exports.resolveParent(doc, selector);
        if (!parent) return false;

        nodes.forEach(function (node) {
            var matchingKid = findChild(node, parent);
            if (matchingKid !== undefined) {
                // stupid elementtree takes an index argument it doesn't use
                // and does not conform to the python lib
                parent.remove(matchingKid);
            }
        });

        return true;
    },

    // restores attributes from doc at selector
    pruneXMLRestore: function (doc, selector, xml) {
        var target = module.exports.resolveParent(doc, selector);
        if (!target) return false;

        if (xml.oldAttrib) {
            target.attrib = _.extend({}, xml.oldAttrib);
        }

        return true;
    },

    pruneXMLRemove: function (doc, selector, nodes) {
        var target = module.exports.resolveParent(doc, selector);
        if (!target) return false;

        nodes.forEach(function (node) {
            var attributes = node.attrib;
            for (var attribute in attributes) {
                if (target.attrib[attribute]) {
                    delete target.attrib[attribute];
                }
            }
        });

        return true;

    },

    parseElementtreeSync: function (filename) {
        var contents = stripBom(fs.readFileSync(filename, 'utf-8'));
        return new et.ElementTree(et.XML(contents));
    },

    resolveParent: function (doc, selector) {
        var parent, tagName, subSelector;

        // handle absolute selector (which elementtree doesn't like)
        if (ROOT.test(selector)) {
            tagName = selector.match(ROOT)[1];
            // test for wildcard "any-tag" root selector
            if (tagName === '*' || tagName === doc._root.tag) {
                parent = doc._root;

                // could be an absolute path, but not selecting the root
                if (ABSOLUTE.test(selector)) {
                    subSelector = selector.match(ABSOLUTE)[2];
                    parent = parent.find(subSelector);
                }
            } else {
                return false;
            }
        } else {
            parent = doc.find(selector);
        }
        return parent;
    }
};

function findChild (node, parent) {
    const matches = parent.findall(node.tag);
    return matches.find(m => module.exports.equalNodes(node, m));
}

function uniqueChild (node, parent) {
    return !findChild(node, parent);
}

// Find the index at which to insert an entry. After is a ;-separated priority list
// of tags after which the insertion should be made. E.g. If we need to
// insert an element C, and the rule is that the order of children has to be
// As, Bs, Cs. After will be equal to "C;B;A".
function findInsertIdx (children, after) {
    var childrenTags = children.map(function (child) { return child.tag; });
    var afters = after.split(';');
    var afterIndexes = afters.map(function (current) { return childrenTags.lastIndexOf(current); });
    var foundIndex = _.find(afterIndexes, function (index) { return index !== -1; });

    // add to the beginning if no matching nodes are found
    return typeof foundIndex === 'undefined' ? 0 : foundIndex + 1;
}

var BLACKLIST = ['platform', 'feature', 'plugin', 'engine'];
var SINGLETONS = ['content', 'author', 'name'];
function mergeXml (src, dest, platform, clobber) {
    // Do nothing for blacklisted tags.
    if (BLACKLIST.includes(src.tag)) return;

    // Handle attributes
    Object.getOwnPropertyNames(src.attrib).forEach(function (attribute) {
        if (clobber || !dest.attrib[attribute]) {
            dest.attrib[attribute] = src.attrib[attribute];
        }
    });
    // Handle text
    if (src.text && (clobber || !dest.text)) {
        dest.text = src.text;
    }
    // Handle children
    src.getchildren().forEach(mergeChild);

    // Handle platform
    if (platform) {
        src.findall('platform[@name="' + platform + '"]').forEach(function (platformElement) {
            platformElement.getchildren().forEach(mergeChild);
        });
    }

    // Handle duplicate preference tags (by name attribute)
    removeDuplicatePreferences(dest);

    function mergeChild (srcChild) {
        var srcTag = srcChild.tag;
        var destChild = new et.Element(srcTag);
        var foundChild;
        var query = srcTag + '';
        var shouldMerge = true;

        if (BLACKLIST.includes(srcTag)) return;

        if (SINGLETONS.includes(srcTag)) {
            foundChild = dest.find(query);
            if (foundChild) {
                destChild = foundChild;
                dest.remove(destChild);
            }
        } else {
            // Check for an exact match and if you find one don't add
            var mergeCandidates = dest.findall(query)
                .filter(function (foundChild) {
                    return foundChild && textMatch(srcChild, foundChild) && attribMatch(srcChild, foundChild);
                });

            if (mergeCandidates.length > 0) {
                destChild = mergeCandidates[0];
                dest.remove(destChild);
                shouldMerge = false;
            }
        }

        mergeXml(srcChild, destChild, platform, clobber && shouldMerge);
        dest.append(destChild);
    }

    function removeDuplicatePreferences (xml) {
        // reduce preference tags to a hashtable to remove dupes
        var prefHash = xml.findall('preference[@name][@value]').reduce(function (previousValue, currentValue) {
            previousValue[ currentValue.attrib.name ] = currentValue.attrib.value;
            return previousValue;
        }, {});

        // remove all preferences
        xml.findall('preference[@name][@value]').forEach(function (pref) {
            xml.remove(pref);
        });

        // write new preferences
        Object.keys(prefHash).forEach(function (key) {
            var element = et.SubElement(xml, 'preference');
            element.set('name', key);
            element.set('value', this[key]);
        }, prefHash);
    }
}

// Expose for testing.
module.exports.mergeXml = mergeXml;

function textMatch (elm1, elm2) {
    var text1 = elm1.text ? elm1.text.replace(/\s+/, '') : '';
    var text2 = elm2.text ? elm2.text.replace(/\s+/, '') : '';
    return (text1 === '' || text1 === text2);
}

function attribMatch (one, two) {
    var oneAttribKeys = Object.keys(one.attrib);
    var twoAttribKeys = Object.keys(two.attrib);

    if (oneAttribKeys.length !== twoAttribKeys.length) {
        return false;
    }

    for (var i = 0; i < oneAttribKeys.length; i++) {
        var attribName = oneAttribKeys[i];

        if (one.attrib[attribName] !== two.attrib[attribName]) {
            return false;
        }
    }

    return true;
}
