/*
 *
 * Copyright 2013 Anis Kadri
 *
 * Licensed 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')
  , path = require('path')
  , _ = require('underscore')
  , et = require('elementtree');

module.exports = {
    moveProjFile: function(origFile, projPath, callback) {
        var src = path.resolve(projPath, origFile)
          , dest = src.replace('.orig', '');

        fs.createReadStream(src)
            .pipe(fs.createWriteStream(dest))
            .on('close', callback);
    },

    // 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;
        }

        var oneAttribKeys = Object.keys(one.attrib),
            twoAttribKeys = Object.keys(two.attrib),
            i = 0, attribName;

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

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

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

        for (i; 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 = resolveParent(doc, selector);
        if (!parent) {
            //Try to create the parent recursively if necessary
            try {
                var parentToCreate = et.XML("<" + path.basename(selector) + ">"),
                    parentSelector = path.dirname(selector);

                this.graftXML(doc, [parentToCreate], parentSelector);
            } catch (e) {
                return false;
            }
            parent = 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;
    },

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

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

        return true;
    },

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

function findChild(node, parent) {
    var matchingKids = parent.findall(node.tag)
      , i, j;

    for (i = 0, j = matchingKids.length ; i < j ; i++) {
        if (module.exports.equalNodes(node, matchingKids[i])) {
            return matchingKids[i];
        }
    }
    return null;
}

function uniqueChild(node, parent) {
    var matchingKids = parent.findall(node.tag)
      , i = 0;

    if (matchingKids.length == 0) {
        return true;
    } else  {
        for (i; i < matchingKids.length; i++) {
            if (module.exports.equalNodes(node, matchingKids[i])) {
                return false;
            }
        }
        return true;
    }
}

var ROOT = /^\/([^\/]*)/,
    ABSOLUTE = /^\/([^\/]*)\/(.*)/;
function resolveParent(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;
}

// 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;
}
