/**
 * Permet de parser une chaine de caractere pour recuperer une liste d'arguments
 **/
KeyValueParser = Class.create();

KeyValueParser.prototype = {
    initialize: function(_separator, _assignement, _ignored, _toParse){
        this.separator = _separator || "&";
        this.assignement = _assignement || "=";
        this.ignored = _ignored || "?";
        this.resultsArray = new Hash();
        
        if (typeof(_toParse) == "string") {
            this.parse(_toParse);
        }
        
    },
    parse: function(_toParse){
        if (typeof(_toParse) != "string") 
            return $H(new Array());
        unescape(_toParse).split(this.separator).each(function(o, i){
            var tuple = o.split(this.assignement);
            // console.debug("parsed tuple:"+tuple);
            /*tableau associatif et incremental*/
            if (tuple.length > 0 && typeof(tuple[0]) == "string" && tuple[0] != "undefined") {
                this.resultsArray[tuple[0]] = tuple[1];
                // console.debug("result:"+this.resultsArray.toString());
            
                // this.resultsArray[i]=tuple[1];
                // console.debug("result:"+this.resultsArray.toString());
            }
            
        }.bind(this));
        // console.debug("result:"+this.resultsArray);
        return this.resultsArray;
    },
    get: function(_indexOrKey){
        return this.resultsArray[_indexOrKey];
    }
    
}

/*Permet de parser une URL pour recuperer ses principales composantes*/
UrlParser = Class.create();

UrlParser.prototype = {
    initialize: function(_toParse){
        this.paramParser = new KeyValueParser("&", "=", "?");
        this.targetParser = new KeyValueParser("&", "=", "#");
        
        if (typeof(_toParse) == "string") 
            this.parse(_toParse);
    },
    parse: function(_toParse){
        // console.group("URL Parsing");
        var toParse = unescape(_toParse);
        // recupere le protocole
        // this.protocol=toParse.split("://")[0];
        var indexOfProtocol = toParse.indexOf("://");
        this.protocol = toParse.substring(0, indexOfProtocol);
        indexOfProtocol += 3;
        // console.info("protocol:"+this.protocol);
        
        // recupere l'url du serveur
        var indexOfHost = toParse.indexOf("/", indexOfProtocol + 1);
        this.host = toParse.substring(indexOfProtocol, indexOfHost);
        // console.info("host:"+this.host);
        
        // recupere l'url sans la page et le dernier /
        var indexOfPath = toParse.lastIndexOf("/");
        this.path = toParse.substring(indexOfHost, indexOfPath);
        // console.info("path:"+this.path);
        
        // recupere la page
        var indexOfParameters = toParse.indexOf("?", indexOfPath);
        // console.debug("indexOfParameters:"+indexOfParameters);
        var indexOfTarget = toParse.indexOf("#", indexOfPath);
        // console.debug("indexOfTarget:"+indexOfTarget);
        var indexOfEndOfPage;
        if (indexOfParameters > 0 && indexOfTarget > 0) {
            indexOfEndOfPage = Math.min(indexOfParameters, indexOfTarget);
            this.page = toParse.substring(indexOfPath, indexOfEndOfPage);
        }
        else 
            if (indexOfParameters > 0) {
                this.page = toParse.substring(indexOfPath, indexOfParameters);
            }
            else 
                if (indexOfTarget > 0) {
                    this.page = toParse.substring(indexOfPath, indexOfTarget);
                }
                else {
                    this.page = toParse.substring(indexOfPath);
                }
        // console.info("page:"+this.page);
        
        // url de la page
        this.url = this.protocol + "://" + this.host + this.path + this.page;
        // console.debug("url:"+this.url);
        
        // recupere les parametres et la cible
        if (indexOfParameters > 0 && indexOfTarget > 0) {
            if (indexOfParameters < indexOfTarget) {
                this.parameters = toParse.substring(indexOfParameters + 1, indexOfTarget);
                // console.info("parameters:"+this.parameters);
                this.target = toParse.substr(indexOfTarget + 1);
                // console.info("target:"+this.target);
            }
            else {
                this.target = toParse.substring(indexOfTarget + 1, indexOfParameters);
                // console.info("target:"+this.target);  
                this.parameters = toParse.substr(indexOfParameters + 1);
                // console.info("parameters:"+this.parameters);
            }
        }
        else 
            if (indexOfParameters > 0) {
                this.target = "";
                // console.info("target: nothing");
                this.parameters = toParse.substr(indexOfParameters + 1);
            // console.info("parameters:"+this.parameters);
            }
            else 
                if (indexOfTarget > 0) {
                    this.parameters = "";
                    // console.info("parameters: nothing");
                    this.target = toParse.substr(indexOfTarget + 1);
                // console.info("target:"+this.parameters);
                }
        
        if (this.target != "") {
            // console.group("Parsing Target : "+this.target);
            this.targetParams = this.targetParser.parse(this.target);
            // console.groupEnd();
            // console.debug("");
        
        }
        else {
            this.targetParams = new Array();
        }
        if (this.parameters != "") {
            // console.group("Parsing Parameters : "+this.parameters);
            this.parametersParams = this.paramParser.parse(this.parameters);
            // console.groupEnd();
            // console.debug("");
        }
        else {
            this.parametersParams = new Array();
        }
        
        
        // console.groupEnd();
        // console.debug("");
    },
    getURL: function(){
        this.url = this.protocol + "://" + this.host + this.path + this.page;
        return this.url;
        
    },
    getFileName: function(){
        return this.page;
    },
    getPath: function(){
        return this.path;
    },
    getTarget: function(_indexOrKey){
        return this.targetParams[_indexOrKey];
    },
    getParam: function(_indexOrKey){
        return this.parametersParams[_indexOrKey];
    },
    getParamQueryString: function(){
        return this.parametersParams.toQueryString();
    },
    getTargetQueryString: function(){
        return this.targetParams.toQueryString();
    }
};

/*Extensions des elements HTML pour plus de praticite*/
Element.addMethods({
    getElementsByHrefHost: function(e, host){
        if (typeof(host) != "string") 
            return undefined;
        return $A($(e).getElementsByTagName("A")).findAll(function(o){
            return (new UrlParser(o.href).host == host);
        });
    },
    getElementsByHrefUrl: function(e, url){
        if (typeof(url) != "string") 
            return undefined;
        return $A($(e).getElementsByTagName("A")).findAll(function(o){
            return (new UrlParser(o.href).url == url);
        });
    },
    getElementsByHrefPage: function(e, page){
        if (typeof(page) != "string") 
            return undefined;
        return $A($(e).getElementsByTagName("A")).findAll(function(o){
            return (new UrlParser(o.href).page == page);
        });
    },
    getElementsByHrefPath: function(e, path){
        if (typeof(path) != "string") 
            return undefined;
        return $A($(e).getElementsByTagName("A")).findAll(function(o){
            return (new UrlParser(o.href).path == path);
        });
    },
    getElementsByHrefURLParameter: function(e, parameter){
        if (typeof(parameter) != "string") 
            return undefined;
        return $A($(e).getElementsByTagName("A")).findAll(function(o){
            return (typeof(new UrlParser(o.href).getParam(parameter))) != 'undefined';
        });
    },
    getElementsByHrefURLParameterValue: function(e, parameter, value){
        if (typeof(parameter) != "string" || typeof(value) != "string") 
            return undefined;
        return $A($(e).getElementsByTagName("A")).findAll(function(o){
            return (new UrlParser(o.href).getParam(parameter) == value);
        });
    },
    getElementsByHrefURLTargetParameter: function(e, parameter){
        if (typeof(target) != "string") 
            return undefined;
        return $A($(e).getElementsByTagName("A")).findAll(function(o){
            return (typeof(new UrlParser(o.href).getTarget(parameter))) != 'undefined';
        });
    },
    getElementsByHrefURLTargetParameterValue: function(e, parameter, value){
        if (typeof(parameter) != "string" || typeof(value) != "string") 
            return undefined;
        return $A($(e).getElementsByTagName("A")).findAll(function(o){
            return (new UrlParser(o.href).getTarget(parameter) == value);
        });
    },
    hasParameterValue: function(e, parameter, value){
        if (!e || !e.href) 
            return false;
        if (typeof(parameter) != "string" || typeof(value) != "string") 
            return false;
        return (new UrlParser(e.href).getParam(parameter) == value);
    },
    hasTargetParameterValue: function(e, parameter, value){
        if (!e || !e.href) 
            return false;
        if (typeof(parameter) != "string" || typeof(value) != "string") 
            return false;
        return (new UrlParser(e.href).getTarget(parameter) == value);
    },
    hasAnyParameterValue: function(e, parameter, value){
        if (!e || !e.href) 
            return false;
        if (typeof(parameter) != "string" || typeof(value) != "string") 
            return false;
        var parser = new UrlParser(e.href);
        return (parser.getTarget(parameter) == value || parser.getParam(parameter) == value);
    }
});


