/*
 * 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.
 *
*/
/* jshint sub:true  */

var _ = require('underscore');

// add the count of [key1][key2]...[keyN] to obj
// return true if it didn't exist before
exports.deep_add = function deep_add (obj, keys /* or key1, key2 .... */) {
    if (!Array.isArray(keys)) {
        keys = Array.prototype.slice.call(arguments, 1);
    }

    return exports.process_munge(obj, true/* createParents */, function (parentArray, k) {
        var found = _.find(parentArray, function (element) {
            return element.xml === k.xml;
        });
        if (found) {
            found.after = found.after || k.after;
            found.count += k.count;
        } else {
            parentArray.push(k);
        }
        return !found;
    }, keys);
};

// decrement the count of [key1][key2]...[keyN] from obj and remove if it reaches 0
// return true if it was removed or not found
exports.deep_remove = function deep_remove (obj, keys /* or key1, key2 .... */) {
    if (!Array.isArray(keys)) {
        keys = Array.prototype.slice.call(arguments, 1);
    }

    var result = exports.process_munge(obj, false/* createParents */, function (parentArray, k) {
        var index = -1;
        var found = _.find(parentArray, function (element) {
            index++;
            return element.xml === k.xml;
        });
        if (found) {
            if (parentArray[index].oldAttrib) {
                k.oldAttrib = _.extend({}, parentArray[index].oldAttrib);
            }
            found.count -= k.count;
            if (found.count > 0) {
                return false;
            } else {
                parentArray.splice(index, 1);
            }
        }
        return undefined;
    }, keys);

    return typeof result === 'undefined' ? true : result;
};

// search for [key1][key2]...[keyN]
// return the object or undefined if not found
exports.deep_find = function deep_find (obj, keys /* or key1, key2 .... */) {
    if (!Array.isArray(keys)) {
        keys = Array.prototype.slice.call(arguments, 1);
    }

    return exports.process_munge(obj, false/* createParents? */, function (parentArray, k) {
        return _.find(parentArray, function (element) {
            return element.xml === (k.xml || k);
        });
    }, keys);
};

// Execute func passing it the parent array and the xmlChild key.
// When createParents is true, add the file and parent items  they are missing
// When createParents is false, stop and return undefined if the file and/or parent items are missing

exports.process_munge = function process_munge (obj, createParents, func, keys /* or key1, key2 .... */) {
    if (!Array.isArray(keys)) {
        keys = Array.prototype.slice.call(arguments, 1);
    }
    var k = keys[0];
    if (keys.length === 1) {
        return func(obj, k);
    } else if (keys.length === 2) {
        if (!obj.parents[k] && !createParents) {
            return undefined;
        }
        obj.parents[k] = obj.parents[k] || [];
        return exports.process_munge(obj.parents[k], createParents, func, keys.slice(1));
    } else if (keys.length === 3) {
        if (!obj.files[k] && !createParents) {
            return undefined;
        }
        obj.files[k] = obj.files[k] || { parents: {} };
        return exports.process_munge(obj.files[k], createParents, func, keys.slice(1));
    } else {
        throw new Error('Invalid key format. Must contain at most 3 elements (file, parent, xmlChild).');
    }
};

// All values from munge are added to base as
// base[file][selector][child] += munge[file][selector][child]
// Returns a munge object containing values that exist in munge
// but not in base.
exports.increment_munge = function increment_munge (base, munge) {
    var diff = { files: {} };

    for (var file in munge.files) {
        for (var selector in munge.files[file].parents) {
            for (var xml_child in munge.files[file].parents[selector]) {
                var val = munge.files[file].parents[selector][xml_child];
                // if node not in base, add it to diff and base
                // else increment it's value in base without adding to diff
                var newlyAdded = exports.deep_add(base, [file, selector, val]);
                if (newlyAdded) {
                    exports.deep_add(diff, file, selector, val);
                }
            }
        }
    }
    return diff;
};

// Update the base munge object as
// base[file][selector][child] -= munge[file][selector][child]
// nodes that reached zero value are removed from base and added to the returned munge
// object.
exports.decrement_munge = function decrement_munge (base, munge) {
    var zeroed = { files: {} };

    for (var file in munge.files) {
        for (var selector in munge.files[file].parents) {
            for (var xml_child in munge.files[file].parents[selector]) {
                var val = munge.files[file].parents[selector][xml_child];
                // if node not in base, add it to diff and base
                // else increment it's value in base without adding to diff
                var removed = exports.deep_remove(base, [file, selector, val]);
                if (removed) {
                    exports.deep_add(zeroed, file, selector, val);
                }
            }
        }
    }
    return zeroed;
};

// For better readability where used
exports.clone_munge = function clone_munge (munge) {
    return exports.increment_munge({}, munge);
};
