/**
 * ................................................................................
 *
 * released under MIT License
 *
 * Copyright (c) 2008 Marc Jansen
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * 
 * ................................................................................
 *
 * Handles URL-like strings to get and set URl-values.
 *
 * @author Marc Jansen <jansen.marc@gmx.de>
 * @license MIT-licensed, see http://www.opensource.org/licenses/mit-license.php
 * @date 2008-03-21
 * @example
 * <pre>
 *   var myURL = 'http://www.example.com/index.php?param1=value1&paramtwo=test';
 *   myObject = new URL( myURL ); //instantiate
 *   alert( myObject.reqCount ); // alerts '2'
 *   alert( myObject.get('paramtwo') ); // alerts 'test'
 *   alert( myObject.get('notthere') === null ); // alerts true
 *   alert( myObject.set('notthere', 'just created') === true ); // alerts true
 *   alert( myObject.reqCount ); // alerts '3'
 *   alert( myObject.get('notthere') ); // alerts 'just created'
 *   alert( myObject.toStr() ); // alerts 'http://www.example.com/index.php?param1=value1&paramtwo=test&notthere=just%20created'
 *   alert( myObject.unset('param1') === true) // alerts true
 *   alert( myObject.unset('stillnotther') === false) // alerts true
 *   alert( myObject.reqCount ); // alerts '2'
 *   alert( myObject.toStr() ); // alerts 'http://www.example.com/index.php?paramtwo=test&notthere=just%20created'
 * </pre>
 * @param {string} the url to handle
 * @todo does not work with arraylike-params: eg val[]=23&val[]=34 or val[1]=23&val[2]=34
 */
var URL = function( urlstr ) {
   /**
    * private variable storing the first part of the url, e.g.
    * http://www.marc-und-julika.de/hendrik.php
    *
    * @var {string} stores the first part of the url
    */
   var firstpart = '';
   
   /**
    * private variable storing the second parts of the url, e.g.
    * {param1 : 'value 1'}
    *
    * @var {object} stores the second part of the url
    */
   var requestObj = {};
   
   /**
    * public variable storing the number of request params
    *
    * @var {integer} stores the fist part of the url
    */
   this.reqCount = 0;
  
   /**
    * privileged method to parse the URL int its parts 
    * @return {object} the object with request params
    */
   this.toObj = function() {
      var urlParts = ( new String( urlstr ) ).split('?');
      firstpart = urlParts[0] || '';
      var requestParts = ( urlParts[1] || '' ).split('&');
      var reqLength = requestParts.length; 
      for(var i  = 0; i < reqLength; i++)  {
          var keyValParts = requestParts[i].split('=');
          requestObj[ unescape( keyValParts[0] ) ]  = unescape( keyValParts[1] || '');
          this.reqCount++;
      }
      return requestObj;
   };
   
   /**
    * privileged method to create the URL from its parts 
    * @return {string} the new url
    */
   this.toStr = function() {
    var arr = [];
    for (reqKey in requestObj) {
      arr[arr.length] = escape(reqKey) + '=' + escape(requestObj[reqKey]);
    }
    return firstpart + '?' + arr.join('&'); 
   };
   
   /**
    * Sets the specified <key> to value <val> (as in <key>=<val>). 
    * Creates such a pair if the key did not exist in the frst place
    * @param {string} the key of the pair
    * @param {string} the value of the pair
    * @return {boolean} whether the key could be set
    */
   this.set = function(key, val) {
     if ( typeof requestObj[key] === 'undefined') {
       this.reqCount++;
     }
     return !!( requestObj[key] = val );
   };
   
   /**
    * Gets the <val> for given key <key> (as in <key>=<val>). 
    * return null if there isn't such a key
    * @param {string} the key of the pair
    * @return {mixed} the value of te pair or null
    */
   this.get = function(key) {
     return requestObj[key] || null; 
   };
   
   /**
    * Unsets the specified <key> (as in <key>=<val>). 
    * @param {string} the key of the pair
    * @return {boolean} whether the key could be unset
    */
   this.unset = function(key) {
     if ( typeof requestObj[key] === 'undefined') {
       return false;
     } else {
       this.reqCount--;
       return !!( delete requestObj[key]);
     }
   };
   // running toObj() immediatly
   this.toObj();
}; //  end of class 'URL'
