define([], function () {
    var exports = {};

    exports.jsonToJS = function (str) {
        return JSON.parse(str);
    };

    var xmlNodeToJS = function (xml) {
        try {
            // Create the return object
            var obj = {};
            if (xml.nodeType === 1) { // element
                // do attributes
                if (xml.attributes.length > 0) {
                    for (var j = 0; j < xml.attributes.length; j++) {
                        var attribute = xml.attributes.item(j);
                        obj['@' + attribute.nodeName] = attribute.nodeValue;
                    }
                }
            } else if (xml.nodeType === 3 || xml.nodeType === 4) { // text
                obj = xml.nodeValue;
            }

            // do children
            if (xml.hasChildNodes()) {
                for (var i = 0; i < xml.childNodes.length; i++) {
                    var item = xml.childNodes.item(i);
                    var nodeName = item.nodeName;
                    if (typeof (obj[nodeName]) === 'undefined') {
                        obj[nodeName] = xmlNodeToJS(item);
                    } else {
                        if (typeof (obj[nodeName].push) === 'undefined') {
                            var old = obj[nodeName];
                            obj[nodeName] = [];
                            obj[nodeName].push(old);
                        }
                        obj[nodeName].push(xmlNodeToJS(item));
                    }
                }
            }
            return obj;
        } catch (e) {
            return {};
        }
    };

    exports.proxyURL = function (url) {

        var proxyUrl = window.location.origin + '/api/data/stream/';

        if (proxyUrl.indexOf('://') > -1)
        {

            if (url.indexOf(proxyUrl) !== -1)
            {
                // url already is a NAPI streaming url
                return url;
            }

            var baseUrl = '';
            if (url.indexOf('://') !== -1) {
                // url is full url
            }
            else if(url[0] === '/')
            {
                // url is relative to root
                var baseUrl = window.location.origin;
            }
            else
            {
                var baseUrl = window.location.href + '/';
                // url is relative to current url
            }
            url = baseUrl + url;

            var encodedUrl = encodeURIComponent(url);
            return proxyUrl + encodedUrl;
        }
        return url;
    };

    exports.replaceTextAndCData = function(obj) {
        if (typeof(obj) === "object") {
          if ('#text' in obj) {
            return obj['#text'];
          }
          if ('#cdata-section' in obj) {
            return obj['#cdata-section'];
          }

          for(var key in obj) {
            if (obj.hasOwnProperty(key)) {
                obj[key] = exports.replaceTextAndCData(obj[key]);

            }
          }
        }
        return obj;
    };

    exports.xmlToJS = function (str, replaceTextAndCData) {
        try {
            if ('DOMParser' in window) {
                var parser = new window.DOMParser();
                var xmlDoc = parser.parseFromString(str.trim(), 'text/xml');
                var obj = xmlNodeToJS(xmlDoc);
                if (replaceTextAndCData) {
                  return exports.replaceTextAndCData(obj);
                }
                return obj;
            }
        } catch (ex) {
            return {};
        }
    };

    exports.queryObject = function (obj, qry) {
        var curObj = obj;
        var result = [];
        var parts = qry.split('.');
        parts.forEach(function(part, i) {
            if (part in curObj) {
                if (i === parts.length - 1) {
                    var resultObj = curObj[part];
                    var type = resultObj.constructor.name;
                    if (type == "Array") {
                        result = [];
                    } else if (type == "Object") {
                        result = {};
                    }
                    var keys = Object.keys(resultObj);
                    for (var prop in keys) {
                        if (type == "Array") {
                            result[prop] = resultObj[prop];
                        } else if (type == "Object") {
                            var propName = keys[prop];
                            result[propName] = resultObj[propName];
                        }
                    }
                } else {
                    curObj = curObj[part];
                }
            } else {
                return false;
            }
        });
        if (!Array.isArray(result)) {
            return [result];
        }
        return result;
    };

    exports.compare = function (a, b, dir) {
        if (!dir) dir = 1;
        var cmp = 0;
        if (a > b) cmp = 1;
        else if (a < b) cmp = -1;
        return dir * cmp;
    };

    exports.compareString = function (a, b, dir) {
        if (!dir) dir = 1;
        return dir * ('' + a).localeCompare('' + b);
    };

    exports.format = function (str) {
        var i;
        for (i = 1; i < arguments.length; i++) {
            str = str.replace('{' + (i - 1) + '}', arguments[i]);
        }
        return str;
    };

    exports.array = function (obj) {
        if (obj !== null && obj !== undefined) {
            if (Array.isArray(obj)) {
                return obj;
            } else {
                return [obj];
            }
        }
        return [];
    };

    exports.truncateSmart = function (str, limit) {
        var bits, i;
        bits = ('' + str).split('');
        if (bits.length > limit) {
            for (i = bits.length - 1; i > -1; --i) {
                if (i > limit) {
                    bits.length = i;
                } else if (' ' === bits[i]) {
                    bits.length = i;
                    break;
                }
            }
            bits.push('...');
        }
        return bits.join('');
    };

    return exports;
});
