/* Translation of Perl module O2::Util::UrlMod

   Usage:
     var newUrl = o2UrlMod.urlMod({
       "setMethod" : "myMethod",
       "setParam"  : "a=1"
     });

   The parameters are the same as in Perl.
*/

require("/o2www/js/util/string.js");

o2UrlMod = {

  // May be used for testing
  setCurrentUrl : function(url) {
    o2UrlMod.currentUrl = url;
  },

  getCurrentUrl : function() {
    return o2UrlMod.currentUrl || document.location.href;
  },

  getQueryString : function() {
    var matches = o2UrlMod.getCurrentUrl().match(/[?]([^#]*)/);
    return matches ? matches[1] : "";
  },

  getParam : function(param) {
    return o2UrlMod.queryStringGetParam( o2UrlMod.getQueryString(), param );
  },

  // Returns the hash part of the url
  getHash : function() {
    var matches = o2UrlMod.getCurrentUrl().match(/[#](.*)$/);
    return matches ? matches[1] : "";
  },

  urlMod : function(params) {
    params = params || {};
    var currentUrl = o2UrlMod.getCurrentUrl().replace(/^https?:\/\/[^\/?]+/, ""); // Stripping away the protocol and server name
    if (params.setDispatcherPath || params.setClass || params.setMethod) {
      var matches = currentUrl.match(/^\/(\w+)\/([-\w:]+)(\/([^?]*))?([?]([^#]+))?(#(.*))?$/);
      if (matches) {
        var preSlash    = matches[1] || "";
        var module      = matches[2] || "";
        var method      = matches[4] || "";
        var queryString = matches[6] || "";
        var hash        = matches[8] || "";
        return o2UrlMod.buildO2Url(preSlash, module, method, queryString, hash, params);
      }
      if (currentUrl.match(/^\/o2admin\/?$/)) {
        return o2UrlMod.buildO2Url("o2admin", "", "", "", "", params);
      }
      if (!params.setDispatcherPath) {
        alert("Missing setDispatcherPath attribute");
      }
      var queryString = o2UrlMod.getQueryString();
      return o2UrlMod.buildO2Url(params.setDispatcherPath, "", "", queryString, "", params);
    }
    // A regular url (not necessarily o2-url)
    var items = split(/[?#]/, o2UrlMod.getCurrentUrl(), 2);
    var baseUrl     = items[0];
    var queryString = o2UrlMod.getQueryString();
    var newQueryString = o2UrlMod.updateQueryString(queryString, params);
    var url = baseUrl;
    if (newQueryString) {
      url += "?" + newQueryString;
    }
    var hash = o2UrlMod.getHash();
    if (hash) {
      url += "#" + hash;
    }
    return url;
  },

  buildO2Url : function(preSlash, module, method, queryString, hash, params) {
    preSlash = params.setDispatcherPath || preSlash;
    module   = params.setClass          || module;
    module   = module.replace(/::/, "-");
    method   = params.setMethod         || method;
    queryString = o2UrlMod.updateQueryString(queryString, params);
    var newUrl = "/" + preSlash + "/" + module + "/" + method;
    if (queryString) {
      newUrl += "?" + queryString;
    }
    if (hash) {
      newUrl += "#" + hash;
    }
    if (params.absoluteURL) {
      newUrl = o2UrlMod.getProtocol() + "://" + o2UrlMod.getHost() + newUrl;
    }
    return newUrl;
  },

  getHost : function() {
    var currentUrl = o2UrlMod.getCurrentUrl();
    var matches = currentUrl.match(/^https?:\/\/([^\/?]+)/);
    if (matches) {
      return matches[1];
    }
    return document.location.href.replace(/^https?:\/\/([^\/?]+).*/, "$1");
  },

  updateQueryString : function(queryString, params) {
    if (params.removeParams) {
      return "";
    }
    if (params.removeParam) {
      queryString = o2UrlMod.updateQueryStringFromRemoveParam(queryString, params.removeParam);
    }
    if (typeof(params.setParams) !== "undefined") {
      queryString = params.setParams;
    }
    if (params.setParam) {
      queryString = o2UrlMod.updateQueryStringFromSetParam(queryString, params.setParam);
    }
    if (params.appendParam) {
      queryString = o2UrlMod.updateQueryStringFromAppendParam(queryString, params.appendParam);
    }
    if (params.toggleParam) {
      queryString = o2UrlMod.updateQueryStringFromToggleParam(queryString, params.toggleParam);
    }
    queryString = queryString ? queryString.replace(/^&/, "") : "";
    return queryString;
  },

  parseParams : function(paramsStr) {
    var params = split(/&/, paramsStr);
    var paramsHash = {};
    for (var i = 0; i < params.length; i++) {
      var param = params[i];
      var keyAndValue = split(/=/, params[i], 2);
      var key   = keyAndValue[0];
      var value = keyAndValue[1];
      params.key = value;
    }
    return paramsHash;
  },

  replaceQueryStringParam : function(queryString, param, value) {
    if (o2UrlMod.queryStringParamExists(queryString, param)) {
      var regEx = new RegExp("(^|&)" + param + "=.*?(&|$)");
      return queryString.replace(regEx, "$1" + param + "=" + value + "$2");
    }
    return o2UrlMod.appendQueryStringParam(queryString, param, value);
  },

  appendQueryStringParam : function(queryString, param, value) {
    if (queryString) {
      queryString += '&';
    }
    queryString += param + "=" + value;
    return queryString;
  },

  queryStringParamExists : function(queryString, param) {
    var regEx = new RegExp("(^|&)" + param + "=(.*?)(&|$)");
    return regEx.test(queryString);
  },

  queryStringGetParam : function(queryString, param) {
    var regEx = new RegExp("(^|&)" + param + "=(.*?)(&|$)");
    var matches = regEx.exec(queryString);
    if (matches) {
      return matches[2];
    }
    return null;
  },

  deleteQueryStringParam : function(queryString, param) {
    var regEx = new RegExp("(^|&)" + param + "=[^&]*", ["g"]);
    return queryString.replace(regEx, "");
  },

  getProtocol : function() {
    var currentUrl = o2UrlMod.getCurrentUrl();
    var matches = currentUrl.match(/^(\w+):/);
    if (matches) {
      return matches[1];
    }
    return "http";
  },

  updateQueryStringFromRemoveParam : function(queryString, removeParam) {
    var removeParams = split(/,/, removeParam);
    for (var i = 0; i < removeParams.length; i++) {
      queryString = o2UrlMod.deleteQueryStringParam(queryString, removeParams[i]);
    }
    return queryString;
  },

  updateQueryStringFromSetParam : function(queryString, setParam) {
    var params = split(/,/, setParam);
    for (var i = 0; i < params.length; i++) {
      var keyAndValue = split(/=/, params[i], 2);
      var key   = keyAndValue[0];
      var value = keyAndValue[1];
      queryString = o2UrlMod.replaceQueryStringParam(queryString, key, value);
    }
    return queryString;
  },

  updateQueryStringFromAppendParam : function(queryString, setParam) {
    var params = split(/,/, setParam);
    for (var i = 0; i < params.length; i++) {
      var keyAndValue = split(/=/, params[i], 2);
      var key   = keyAndValue[0];
      var value = keyAndValue[1];
      queryString = o2UrlMod.appendQueryStringParam(queryString, key, value);
    }
    return queryString;
  },

  // Example: toggleParam => a=1|2|3,b=4|5|6
  updateQueryStringFromToggleParam : function(queryString, toggleParams) {
    queryString = queryString || "";
    var toggles = split(/,\s*/, toggleParams);
    for (var i = 0; i < toggles.length; i++) {
      var keyAndValue = split(/=/, toggles[i], 2);
      var key    = keyAndValue[0];
      var values = keyAndValue[1];
      var values = split(/\|/, values);
      var hashValues = {};
      var oldValue = o2UrlMod.queryStringGetParam(queryString, key);
      if (oldValue) {
        // arrange so e.g when toggle values is 0|1|2, toggle sequence should be like this 
        // value : toggle to value
        //  0 : 1
        //  1 : 2
        //  2 : 0
        var value;
        var firstToggleValue = values[0];
        for (var j = 0; j < values.length; j++) {
          if (oldValue === values[j]  &&  j < values.length) {
            value = values[j+1];
          }
        }
        if (!value) {
          value = firstToggleValue;
        }
        queryString = o2UrlMod.replaceQueryStringParam(queryString, key, value);
      }
      else {
        queryString = o2UrlMod.replaceQueryStringParam(queryString, key, values[0]);
      }
    }
    return queryString;
  }

};
