/**
 * URL Utilities
 * @module Ink.Util.Url_1
 * @version 1
 */

Ink.createModule('Ink.Util.Url', '1', [], function() {

    'use strict';

    /**
     * @namespace Ink.Util.Url_1
     */
    var Url = {

        /**
         * Auxiliary string for encoding
         *
         * @property _keyStr
         * @type {String}
         * @readOnly
         * @private
         */
        _keyStr : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',


        /**
         * Gets URL of current page
         *
         * @method getUrl
         * @return {String} Current URL
         * @public
         * @static
         * @sample Ink_Util_Url_getUrl.html 
         */
        getUrl: function()
        {
            return window.location.href;
        },

        /**
         * Generates an URL string.
         *
         * @method genQueryString
         * @param {String} uri      Base URL
         * @param {Object} params   Object to transform to query string
         * @return {String} URI with query string set
         * @public
         * @static
         * @sample Ink_Util_Url_genQueryString.html 
         */
        genQueryString: function(uri, params) {
            var hasQuestionMark = uri.indexOf('?') !== -1;
            var sep, pKey, pValue, parts = [uri];

            for (pKey in params) {
                if (params.hasOwnProperty(pKey)) {
                    if (!hasQuestionMark) {
                        sep = '?';
                        hasQuestionMark = true;
                    } else {
                        sep = '&';
                    }
                    pValue = params[pKey];
                    if (typeof pValue !== 'number' && !pValue) {
                        pValue = '';
                    }
                    parts = parts.concat([sep, encodeURIComponent(pKey), '=', encodeURIComponent(pValue)]);
                }
            }

            return parts.join('');
        },

        /**
         * Gets an object from an URL encoded string.
         *
         * @method getQueryString
         * @param   {String} [str]      URL String. When not specified it uses the current URL.
         * @return  {Object}            Key-Value pair object
         * @public
         * @static
         * @sample Ink_Util_Url_getQueryString.html 
         */
        getQueryString: function(str)
        {
            var url;
            if(str && typeof(str) !== 'undefined') {
                url = str;
            } else {
                url = this.getUrl();
            }
            var aParams = {};
            if(url.match(/\?(.+)/i)) {
                var queryStr = url.replace(/^(.*)\?([^\#]+)(\#(.*))?/g, "$2");
                if(queryStr.length > 0) {
                    var aQueryStr = queryStr.split(/[;&]/);
                    for(var i=0; i < aQueryStr.length; i++) {
                        var pairVar = aQueryStr[i].split('=');
                        aParams[decodeURIComponent(pairVar[0])] = (typeof(pairVar[1]) !== 'undefined' && pairVar[1]) ? decodeURIComponent(pairVar[1]) : false;
                    }
                }
            }
            return aParams;
        },

        /**
         * Gets the URL hash value
         *
         * @method getAnchor
         * @param   {String}            [str]   URL String. Defaults to current page URL.
         * @return  {String|Boolean}            Hash in the URL. If there's no hash, returns false.
         * @public
         * @static
         * @sample Ink_Util_Url_getAnchor.html 
         */
        getAnchor: function(str)
        {
            var url;
            if(str && typeof(str) !== 'undefined') {
                url = str;
            } else {
                url = this.getUrl();
            }
            var anchor = false;
            if(url.match(/#(.+)/)) {
                anchor = url.replace(/([^#]+)#(.*)/, "$2");
            }
            return anchor;
        },

        /**
         * Gets the anchor string of an URL
         *
         * @method getAnchorString
         * @param   {String} [string]   URL to parse. Defaults to current URL.
         * @return  {Object}            Key-value pair object of the URL's hashtag 'variables'
         * @public
         * @static
         * @sample Ink_Util_Url_getAnchorString.html 
         */
        getAnchorString: function(string)
        {
            var url;
            if(string && typeof(string) !== 'undefined') {
                url = string;
            } else {
                url = this.getUrl();
            }
            var aParams = {};
            if(url.match(/#(.+)/i)) {
                var anchorStr = url.replace(/^([^#]+)#(.*)?/g, "$2");
                if(anchorStr.length > 0) {
                    var aAnchorStr = anchorStr.split(/[;&]/);
                    for(var i=0; i < aAnchorStr.length; i++) {
                        var pairVar = aAnchorStr[i].split('=');
                        aParams[decodeURIComponent(pairVar[0])] = (typeof(pairVar[1]) !== 'undefined' && pairVar[1]) ? decodeURIComponent(pairVar[1]) : false;
                    }
                }
            }
            return aParams;
        },


        /**
         * Parses URL string into URL parts
         *
         * @method parseUrl
         * @param {String} url URL to be parsed
         * @return {Object} Parsed URL as a key-value object.
         * @public
         * @static
         * @sample Ink_Util_Url_parseUrl.html 
         */
        parseUrl: function(url) {
            var aURL = {};
            if(url && typeof url === 'string') {
                if(url.match(/^([^:]+):\/\//i)) {
                    var re = /^([^:]+):\/\/([^\/]*)\/?([^\?#]*)\??([^#]*)#?(.*)/i;
                    if(url.match(re)) {
                        aURL.scheme   = url.replace(re, "$1");
                        aURL.host     = url.replace(re, "$2");
                        aURL.path     = '/'+url.replace(re, "$3");
                        aURL.query    = url.replace(re, "$4") || false;
                        aURL.fragment = url.replace(re, "$5") || false;
                    }
                } else {
                    var re1 = new RegExp("^([^\\?]+)\\?([^#]+)#(.*)", "i");
                    var re2 = new RegExp("^([^\\?]+)\\?([^#]+)#?", "i");
                    var re3 = new RegExp("^([^\\?]+)\\??", "i");
                    if(url.match(re1)) {
                        aURL.scheme   = false;
                        aURL.host     = false;
                        aURL.path     = url.replace(re1, "$1");
                        aURL.query    = url.replace(re1, "$2");
                        aURL.fragment = url.replace(re1, "$3");
                    } else if(url.match(re2)) {
                        aURL.scheme = false;
                        aURL.host   = false;
                        aURL.path   = url.replace(re2, "$1");
                        aURL.query  = url.replace(re2, "$2");
                        aURL.fragment = false;
                    } else if(url.match(re3)) {
                        aURL.scheme   = false;
                        aURL.host     = false;
                        aURL.path     = url.replace(re3, "$1");
                        aURL.query    = false;
                        aURL.fragment = false;
                    }
                }
                if(aURL.host) {
                    var regPort = /^(.*?)\\:(\\d+)$/i;
                    // check for port
                    if(aURL.host.match(regPort)) {
                        var tmpHost1 = aURL.host;
                        aURL.host = tmpHost1.replace(regPort, "$1");
                        aURL.port = tmpHost1.replace(regPort, "$2");
                    } else {
                        aURL.port = false;
                    }
                    // check for user and pass
                    if(aURL.host.match(/@/i)) {
                        var tmpHost2 = aURL.host;
                        aURL.host = tmpHost2.split('@')[1];
                        var tmpUserPass = tmpHost2.split('@')[0];
                        if(tmpUserPass.match(/\:/)) {
                            aURL.user = tmpUserPass.split(':')[0];
                            aURL.pass = tmpUserPass.split(':')[1];
                        } else {
                            aURL.user = tmpUserPass;
                            aURL.pass = false;
                        }
                    }
                }
            }
            return aURL;
        },

        /**
         * Formats an URL object into an URL string.
         *
         * @method format
         * @param {String|Location|Object} urlObj Window.location, a.href, or parseUrl object to format
         * @return {String} Full URL.
         */
        format: function (urlObj) {
            var protocol = '';
            var host = '';
            var path = '';
            var frag = '';
            var query = '';

            if (typeof urlObj.protocol === 'string') {
                protocol = urlObj.protocol + '//';  // here it comes with the colon
            } else if (typeof urlObj.scheme === 'string')  {
                protocol = urlObj.scheme + '://';
            }

            host = urlObj.host || urlObj.hostname || '';
            path = urlObj.path || '';

            if (typeof urlObj.query === 'string') {
                query = urlObj.query;
            } else if (typeof urlObj.search === 'string') {
                query = urlObj.search.replace(/^\?/, '');
            }
            if (typeof urlObj.fragment === 'string') {
                frag =  urlObj.fragment;
            } else if (typeof urlObj.hash === 'string') {
                frag = urlObj.hash.replace(/#$/, '');
            }

            return [
                protocol,
                host,
                path,
                query && '?' + query,
                frag && '#' + frag
            ].join('');
        },

        /**
         * Gets the last loaded script element
         *
         * @method currentScriptElement
         * @param {String} [match] String to match against the script src attribute
         * @return {DOMElement|Boolean} Returns the `script` DOM Element or false if unable to find it.
         * @public
         * @static
         * @sample Ink_Util_Url_currentScriptElement.html 
         */
        currentScriptElement: function(match)
        {
            var aScripts = document.getElementsByTagName('script');
            if(typeof(match) === 'undefined') {
                if(aScripts.length > 0) {
                    return aScripts[(aScripts.length - 1)];
                } else {
                    return false;
                }
            } else {
                var curScript = false;
                var re = new RegExp(""+match+"", "i");
                for(var i=0, total = aScripts.length; i < total; i++) {
                    curScript = aScripts[i];
                    if(re.test(curScript.src)) {
                        return curScript;
                    }
                }
                return false;
            }
        }
    };

    return Url;

});
