/**
 * @class ep
 * 
 */

/*
 * @copyright		© Copyright 2006-2010, epages GmbH, All Rights Reserved.
 *
 * @module			ep.uri
 */

define("ep/uri", [
	"jquery",
	"ep",
	"util/string",

	"jquery/param"
], function ($, ep, str) {

	var uriExpr = /^((?:(.+)\:\/\/([^\/]+))?((?:\/|[^\?#]).*?)?(\?.*?)?(#.*)?)$/,
		absExpr = /^((http|https|ftp)\:\/\/|\/)/g;

	ep.extend({
		/**
		 * Join or segment a uri.
		 * 
		 * The `ep.uriSegment()` method segments or joins a uri in some parts.
		 * 
		 * ====Parts:====
		 * 
		 *  + '''href''' The full uri.
		 *  + '''protocol''' The protocol ''http'' or ''https''.
		 *  + '''host''' The host name for example www.epages.com
		 *  + '''path''' The dir path. ''/path/example.html''
		 *  + '''query''' The get parameters. ''?foo=bar&data=more''
		 *  + '''anchor''' Anchor id. ''#id''
		 *  + '''parameters''' The query data as object. ''{foo:"bar", data:"more"}''
		 * 
		 * ### Examples
		 * Segment a uri.
		 * 
		 * JavaScript:
		 * 
		 *     ep.uriSegment('http://www.epages.com/de/images/example.jpg?size=xl#center');
		 * 
		 * Results:
		 * 
		 *     {
		 *         "href": "http://www.epages.com/de/images/example.jpg?size=xl#center",
		 *         "protocol": "http",
		 *         "host": "www.epages.com",
		 *         "path": "de/images/example.jpg",
		 *         "query": "?size=xl",
		 *         "anchor": "#center",
		 *         "parameters": {
		 *             "size": "xl"
		 *         }
		 *     }
		 * 
		 * Join uri parts.
		 * 
		 * JavaScript:
		 * 
		 *     ep.uriSegment({
		 *         "protocol": "http",
		 *         "host": "www.epages.com",
		 *         "path": "de/images/example.jpg",
		 *         "anchor": "#center",
		 *         "parameters": {
		 *             "size": "xl"
		 *         }
		 *     });
		 * 
		 * Results:
		 * 
		 *     http://www.epages.com/de/images/example.jpg?size=xl#center
		 * 
		 * 
		 * ### Dependencies
		 * 
		 *  + `ep`
		 * 
		 * @param {String or Object} uri A uri string or object.
		 * 
		 * @method uriSegment
		 * @static 
		 * @member ep
		 * 
		 * @since 6.11.0
		 */
		uriSegment: function( obj ) {
			var ret;
			if( typeof obj === 'string' ){
				var parts = obj.match(uriExpr);

				ret = parts ? {
					'href': parts[1] || '',
					'protocol':parts[2] || '',
					'host': parts[3] || '',
					'path': parts[4] ? parts[4].replace(/\/?(.*)$/i,"$1") : '',
					'query': parts[5] || '',
					'anchor': parts[6] || '',
					'parameters': parts[5] ? $.param( parts[5] ) : {}
				} : {};
			}
			else if( typeof obj === 'object' ){
				ret = '';
				ret += obj.protocol ? obj.protocol + '://' : '';
				ret += obj.host ? obj.host + '/' : '';
				ret += obj.path ? obj.path.replace(/\/?(.*)$/i,"$1") : '';

				if( obj.parameters ){
					var queryString = $.param(obj.parameters);
					ret += queryString ? '?'+queryString : '';
				}
				else{
					ret += obj.query || '';
				}

				ret += obj.anchor || '';
			}
			return ret;
		},

		/**
		 * Encode or decode query arguments of a uri.
		 * 
		 * The `ep.uriQuery()` method decode the query arguments of a uri, to an object or encode a object to a uri query, it works like the `jQuery.param()` method.
		 * 
		 * ### Examples
		 * Decode a uri query.
		 * 
		 * JavaScript:
		 * 
		 *     ep.uriQuery( 'banana=yellow&strawberry=red&group%5Bred%5D=strawberry&group%5Bblue%5D%5B%5D=berry&group%5Bblue%5D%5B%5D=other&group%5Bblue%5D%5B%5D=%5B%5D' );
		 * 
		 * Results:
		 * 
		 *     {
		 *         "banana": "yellow",
		 *         "strawberry": "red",
		 *         "group": {
		 *             "red": "strawberry",
		 *             "blue": [ "berry", "other", "[]" ]
		 *         }
		 *     }
		 * 
		 * Encode object to uri query.
		 * 
		 * JavaScript:
		 * 
		 *     ep.uriQuery({
		 *         "banana": "yellow",
		 *         "strawberry": "red",
		 *         "group": {
		 *             "red": "strawberry",
		 *             "blue": [ "berry", "other", "[]" ]
		 *         }
		 *     });
		 * 
		 * Results:
		 * 
		 *     banana=yellow&strawberry=red&group%5Bred%5D=strawberry&group%5Bblue%5D%5B%5D=berry&group%5Bblue%5D%5B%5D=other&group%5Bblue%5D%5B%5D=%5B%5D
		 * 
		 * 
		 * ### Dependencies
		 * 
		 *  + `ep`
		 * 
		 * @param {String or Object} query A query of a uri or a map of data.
		 * 
		 * @method uriQuery
		 * @static 
		 * @member ep
		 * 
		 * @since 6.11.0
		 */
		uriQuery: function (obj)  {
			ep.deprecated("'ep.uriQuery()' is replaced by 'jQuery.param()'", true);

			return $.param(obj);
		},

		/**
		 * Check uri is abolute.
		 * 
		 * The `ep.uriIsAbsolute()` method check whether a url is absolute, this means if the url begins with ''http'' or ''https''.
		 * 
		 * ### Examples
		 * Check uri is abolute.
		 * 
		 * JavaScript:
		 * 
		 *     ep.uriIsAbsolute('http://www.epages.com/de/images/example.jpg?size=xl#center')
		 * 
		 * Results:
		 * 
		 *     true
		 * 
		 * 
		 * ### Dependencies
		 * 
		 *  + `ep`
		 * 
		 * @param {String} uri A url to check.
		 * 
		 * @method uriIsAbsolute
		 * @static 
		 * @member ep
		 * 
		 * @since 6.11.0
		 */
		uriIsAbsolute: function( url ){
			return absExpr.test(url);
		},

		/**
		 * Convert a relative uri to an absolute uri.
		 * 
		 * The `ep.uriToAbsolute()` method convert a relative uri to an absolute uri based on an other uri.
		 * 
		 * ### Examples
		 * Convert a relative uri to an absolute uri.
		 * 
		 * JavaScript:
		 * 
		 *     ep.uriToAbsolute( '/de/images/example.jpg?size=xl#center', 'http://www.epages.com/de/' );
		 * 
		 * Results:
		 * 
		 *     http://www.epages.com/de/images/example.jpg?size=xl#center
		 * 
		 * 
		 * ### Dependencies
		 * 
		 *  + `ep`
		 * 
		 * @param {String} uri A relative uri.
		 * @param {String} [base] An absolute uri.
		 * 
		 * @method uriToAbsolute
		 * @static 
		 * @member ep
		 * 
		 * @since 6.11.0
		 */
		uriToAbsolute: function( url, baseUrl ){
			return (baseUrl || ep.config.baseUrl).replace(/(\/)$/,'') + "/" + ep.uriToRelative( url, baseUrl );
		},

		/**
		 * Convert a absolute uri to an relative uri.
		 * 
		 * The `ep.uriToRelative()` method convert a absolute uri to a uri absolute to an other uri.
		 * 
		 * ### Examples
		 * Convert a absolute uri to an relative uri.
		 * 
		 * JavaScript:
		 * 
		 *     ep.uriToRelative( 'http://www.epages.com/de/images/example.jpg?size=xl#center', 'http://www.epages.com/de/' );
		 * 
		 * Results:
		 * 
		 *     images/example.jpg?size=xl#center
		 * 
		 * 
		 * ### Dependencies
		 * 
		 *  + `ep`
		 * 
		 * @param {String} uri An absolute uri.
		 * @param {String} [base] A relative uri.
		 * 
		 * @method uriToRelative
		 * @static 
		 * @member ep
		 * 
		 * @since 6.11.0
		 */
		uriToRelative: function( url, baseUrl ){
			var srcUrl = url;
			url = ep.uriSegment( url );
			baseUrl = ep.uriSegment( baseUrl || ep.config.baseUrl );

			if ( (url.protocol && url.protocol !== baseUrl.protocol) || (url.host && url.host !== baseUrl.host) ){
				return srcUrl;
			}

			var parts = str.escExpStr( baseUrl.path.replace(/^\/?(.*)$/i,"$1").replace(/(.*)\/$/i,"$1") ).split('\\/'),
				exprArr = [];

			for( var i=parts.length-1 ; i>=0 ; i-- ){
				exprArr.unshift(parts[i]);

				var expr = new RegExp( '^(' + exprArr.join('\\/') + ')', '' );

				if( expr.test(url.path) ){
					url.path = url.path.replace(expr,'').replace(/^(\/)/,'');
					break;
				}
			}

			return ep.uriSegment({
				'path': url.path,
				'query': url.query,
				'anchor': url.anchor,
				'parameters': url.params
			});
		}
	});

	return ep;

});