window.i3.std.string = {};

window.i3.std.string.strip = window.__String_strip__ = function(string)
{
    if (string === undefined)
        return false;
        
    string = String(string);
    
    for(var j=1; j<arguments.length; j++)
    {              
      var ch = arguments[j];
      var str = string.replace(new RegExp("^"+ch+ch+"*"), ''), ws = new RegExp(ch), i = str.length;
      while (ws.test(str.charAt(--i)));
      str = str.slice(0, i + 1);
    }

    return str;
};
    
window.i3.std.string.stripW = window.__String_stripW__ = function(string)
{
    return i3.std.string.strip(string, "\\s");
 };

window.i3.std.string.between = window.__String_between__ = function(string, char1, char2)
{
    if (string === undefined)
        return false;
        
    string = String(string);
    
    if (char1 && string.indexOf(char1)==-1)
        return '';

    var pos1 = char1 ? string.indexOf(char1) + char1.length : 0;
    var pos2 = char2 && string.indexOf(char2, pos1)!=-1 ? string.indexOf(char2, pos1) : string.length;

    if (string)
        return string.substring(pos1,pos2);
    else
        return '';	
};

window.i3.std.string.betweenA = window.__String_betweenA__ = function(str, strArray, text)
{
    if (string === undefined)
        return false;
        
    string = String(string);
    
    if (text && text.indexOf(str)!=-1)
    {
        if (strArray && typeof strArray == "object")
            for (var i=0; i<strArray.length; i++)
                if (text.indexOf(strArray[i])!=-1)
                    return text.substring(text.indexOf(str)+str.length,text.indexOf(strArray[i]));
        
        return text.substr(text.indexOf(str)+str.length);
    }
    else
        return '';	
};

/* isNumeric thanks to CodeToad, http://www.codetoad.com/javascript/isnumeric.asp, with modifications */
window.i3.std.string.isNumeric = window.__String_isNumeric__ = function(string, type)
{
    if (string === undefined)
        return false;
        
    string = String(string);
    
    var ValidChars = type == 'integer' ? "0123456789" : "0123456789.-";
    var IsNumber = true;
    var Char;

    if (string.length == 0)
        IsNumber = false;
    else
    for (i = 0; i < string.length && IsNumber == true; i++)
    {
        Char = string.charAt(i);
        if (ValidChars.indexOf(Char) == -1 && (type == 'integer' && i == 0 ? Char != '0' : true))
            IsNumber = false;
    };

    return IsNumber;
};

window.i3.std.string.isLogical = window.__String_isLogical__ = function(string)
{
    if (string === undefined)
        return false;
        
    string = String(string);
    
    if (string == 'true' || string == 'false')
        return true;
    else
        return false;
};

window.i3.std.string.isVector = window.__String__isVector__ = function(string, model)
{
    if (string === undefined)
        return false;
        
    string = String(string);
    
    switch (model)
    {
        case '()': 
        if (string.indexOf('(') != -1 && string.indexOf(')') != -1 && string.indexOf(',') != -1)
            return true;
         
        case '[]':
        if (string.indexOf('[') != -1 && string.indexOf(']') != -1 && string.indexOf(',') != -1)
            return true;
         
        case '{}':
        if (string.indexOf('{') != -1 && string.indexOf('}') != -1 && string.indexOf(',') != -1)
            return true;

        default:
        if (string.indexOf(',') != -1)
            return true;
    }
    
    return false;
};

window.i3.std.string.isJSON = function(string)
{
    if (string === undefined)
        return false;
        
    string = String(string);
    
    return /^[\],:{}\s]*$/.test(string.replace(/\\["\\\/bfnrtu]/g, '@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').replace(/(?:^|:|,)(?:\s*\[)+/g, ''));
}

window.i3.std.string.parseJSON = function(string)
{
    if (string === undefined)
        return false;
        
    string = String(string);
    
    if ($.browser.msie)
    {
        try
        {
            return eval("("+string+")");
        }
        catch(e)
        {
            return false;
        }
    }
    else
        try
        {
            return window.JSON ? window.JSON.parse(string) : false;
        }
        catch(e)
        {
            return false;
        }
}

window.i3.std.string.toNumeric = window.__String_toNumeric__ = function(string, type)
{
    if (string === undefined)
        return null;
        
    string = String(string);
    
    if (i3.std.string.isNumeric(string, type))
        return parseFloat(string, type);
    else if (i3.std.string.isNumeric(string))
        return parseInt(string);
    else return null;
};

window.i3.std.string.toLogical = window.__String_toLogical__ = function(string)
{
    if (string === undefined)
        return null;
        
    string = String(string);
    
    if (i3.std.string.isLogical(string))
        return string=='true';
    else return null;
};


window.i3.std.string.toVector = window.__String_toVector__ = function(string, model)
{
    if (string === undefined)
        return null;
        
    string = String(string);
    
    var vector = new Array();
    if (i3.std.string.isVector(string,model))
    {
        var words = string.substring(1,string.length-1).split(',');
        for (var i=0; i<words.length; i++)
            vector.push(parseFloat(words[i]));
        return vector;
    }
    else return null;
};

window.i3.std.string.toFunction = window.__String_toFunction__ = function(string)
{
    if (string === undefined)
        return null;
        
    string = String(string);
    
    try
    {
        return new Function(string);
    }
    catch(e)
    {
        console.log("i3.std.string",e," in "+string);
    }
};

window.i3.std.string.toCamelcase = window.__String_toCamelcase__ = function(string)
{
    if (string === undefined)
        return null;
        
    string = String(string);
    
    return string.replace(/\-(.)/g, function(m, l){return l.toUpperCase()});
};

window.i3.std.string.toArray = window.__String_toArray__ = function(string, seps)
{	
    if (string === undefined)
        return null;
    
     var ret = new Array();
     var seps = i3.std.def(seps,[';',',',':']);
     
     if (!i3.std.string.search(string, seps))
      return string;

     if (seps[0])
     {
      if (string.indexOf(seps[0])!=-1)
      {
       var words = new Array();
       var syllabels = string.split(seps[0]);
       var word = "";
       
       if (seps.length > 1)
       {
        for (var i=0; i<syllabels.length; i++)
	    {
	     if (word != '' && syllabels[i].indexOf(seps[1]) != -1)
	     {
		     words.push(i3.std.string.stripW(word));
		     word = "";
	     }
	     word += (word!=""?seps[0]:"") + syllabels[i];
	    }
	    words.push(i3.std.string.stripW(word));
       }
       else words = syllabels;
       
       for (var i=0; i<words.length; i++)
       {
	    var word = i3.std.string.stripW(words[i]);
        if (seps.length > 1)
 	     ret.push(i3.std.string.toArray(words[i],seps.slice(1)));	
        else
	     ret.push(i3.std.def(i3.std.string.toLogical(word),i3.std.string.toNumeric(word),i3.std.string.toVector(word,'()'),word));
       }
      }
      else return i3.std.string.toArray(string,seps.slice(1));
     }
     
     return ret;
};

window.i3.std.string.parse = function(string)
{
    if (string === undefined)
        return false;
        
    string = String(string);
    
    if (string.charAt(0) == '{' && string.charAt(string.length-1) == '}')
        string = string.substring(1,string.length-1);
    else
        return false;    
    
    if ((string.match(/{/g) ? string.match(/{/g).length : 0) == (string.match(/}/g) ? string.match(/}/g).length : 0))
    {
        var array = [];
        var matches = string.split(',');        
        var part = matches.shift();

        while(matches.length > 0)
        {
          if ((part.match(/{/g) ? part.match(/{/g).length : 0) == (part.match(/}/g) ? part.match(/}/g).length : 0))
          {
              if (part.length > 0)
                  array.push(part);
              part = matches.shift();
          }
          else
              part += "," + matches.shift();
        } 

        if (part.length > 0)
          array.push(part);

        for(var i=0; i<array.length; i++)
        {
          var del = array[i].indexOf(':');
          if (del != -1)
          {
              var label = i3.std.string.strip(array[i].substring(0,del), '\\s', "'", '"');
              var value = i3.std.string.strip(array[i].substring(del+1), '\\s', "'", '"');
              
              if (value.match(/^{.+}$/))
                  value = i3.std.string.parse(value);
              else
                  value = (value.indexOf('@') === 0 ? value.substring(1) : '"'+value+'"');
              
              array[i] = '"'+label+'":'+value;
          }
          else
          {
              array.splice(i, 1);
              i--;
          }
        }
      
        return "{"+array.join(',')+"}";
    }
    else
        return false;
}

window.i3.std.string.toObject = function(string)
{
    if (string === undefined)
        return {};
        
    string = String(string);
    
    var parse = i3.std.string.parse(string);
    return parse && i3.std.string.isJSON(parse) ? i3.std.string.parseJSON(parse) : i3.std.string.unserialize(string.replace(/[;,]/g,'&').replace(/:/g,'='));
}

window.i3.std.string.toXmlEntities = window.__String_toXmlEntities__ = function(string)
{
    if (string === undefined)
        return false;
        
    string = String(string);
    
    return string.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/'/g,'&apos;').replace(/"/g,'&quot;');
};

window.i3.std.string.count = window.__String_count__ = function(string, char)
{
    if (string === undefined)
        return false;
        
    string = String(string);
    
    var amm = 0;
    for (var i=0; i<string.length; i++)
        if (string.charAt(i) == char)
    amm++;

    return amm;
};

window.i3.std.string.search = window.__String_count__ = function(string, thing)
{
    if (string === undefined)
        return false;
        
    string = String(string);
    
	for (var i=0; i<thing.length; i++)
		if (string.indexOf(thing[i])!=-1)
			return true;
};

window.i3.std.string.random = window.__String_random__ = function(length)
{
	var charArray = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
	
	var string = "";
	for (var i=0; i<length; i++)
		string += charArray.charAt(Math.random()*Math.pow(10,3)%charArray.length);

	return string;
};

window.i3.std.string.first = function(string)
{
    if (string === undefined)
        return false;
        
    string = String(string);
    
	var pos = min = string.length;
	for (var i=1; i<arguments.length; i++)
	{
		if ((pos = string.indexOf(arguments[i])) != -1 && pos < min)
			min = pos;
	}
			
	return min;
};

window.i3.std.string.last = function(string)
{
    if (string === undefined)
        return false;
        
    string = String(string);
    
	var pos = max = 0;
	for (var i=1; i<arguments.length; i++)
		if ((pos = string.lastIndexOf(arguments[i])) != -1 && pos > max)
			max = pos;
			
	return max;
};

window.i3.std.string.split = function(string)
{
    if (string === undefined)
        return false;
        
    string = String(string);
    
	var ret = new Array();
	var pos = 0;
	for (var i=1; i<arguments.length; i++)
	{
		ret.push(string.substring(pos, arguments[i]));
		pos = arguments[i];
	}
	
	ret.push(string.substr(pos));
	return ret;
};

/* thanks to phpjs, http://phpjs.org/functions/number_format:481 */
window.i3.std.string.numberFormat = function(number, decimals, dec_point, thousands_sep) {
    number = (number+'').replace(',', '').replace(' ', '');
    var n = !isFinite(+number) ? 0 : +number, 
        prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
        sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
        dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
        s = '',
        toFixedFix = function (n, prec) {
            var k = Math.pow(10, prec);
            return '' + Math.round(n * k) / k;
        };
    // Fix for IE parseFloat(0.55).toFixed(0) = 0;
    s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
    if (s[0].length > 3) {
        s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
    }
    if ((s[1] || '').length < prec) {
        s[1] = s[1] || '';
        s[1] += new Array(prec - s[1].length + 1).join('0');
    }
    return s.join(dec);
};

window.i3.std.string.unserialize = function(string)
{
    var ret = new Object();
    var vars = string.split('&');
    
    for (var j=0; j<vars.length; j++)
    {
        var array = vars[j].split('=');
        var index = i3.std.string.stripW(array[0]);
        var value = i3.std.string.stripW(array[1]);
        
        if (i3.std.string.isNumeric(value))
            ret[index] = i3.std.string.toNumeric(value);
        else if (i3.std.string.isLogical(value))
            ret[index] = i3.std.string.toLogical(value);
        else if (i3.std.string.isVector(value))
            ret[index] = i3.std.string.toVector(value);
        else
            ret[index] = value;
    }
    
    return ret;
}

/* thanks to phpjs, http://phpjs.org/functions/parse_url:485 */

window.i3.std.string.parse_url = function(str, component) {
    // http://kevin.vanzonneveld.net
    // +      original by: Steven Levithan (http://blog.stevenlevithan.com)
    // + reimplemented by: Brett Zamir (http://brett-zamir.me)
    // %          note: Based on http://stevenlevithan.com/demo/parseuri/js/assets/parseuri.js
    // %          note: blog post at http://blog.stevenlevithan.com/archives/parseuri
    // %          note: demo at http://stevenlevithan.com/demo/parseuri/js/assets/parseuri.js
    // %          note: Does not replace invaild characters with '_' as in PHP, nor does it return false with
    // %          note: a seriously malformed URL.
    // %          note: Besides function name, is the same as parseUri besides the commented out portion
    // %          note: and the additional section following, as well as our allowing an extra slash after
    // %          note: the scheme/protocol (to allow file:/// as in PHP)
    // *     example 1: parse_url('http://username:password@hostname/path?arg=value#anchor');
    // *     returns 1: {scheme: 'http', host: 'hostname', user: 'username', pass: 'password', path: '/path', query: 'arg=value', fragment: 'anchor'}

    var  o   = {
        strictMode: false,
        key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
        q:   {
            name:   "queryKey",
            parser: /(?:^|&)([^&=]*)=?([^&]*)/g
        },
        parser: {
            strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
            loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/\/?)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // Added one optional slash to post-protocol to catch file:/// (should restrict this)
        }
    };
    
    var m   = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
    uri = {},
    i   = 14;
    while (i--) {uri[o.key[i]] = m[i] || "";}
    // Uncomment the following to use the original more detailed (non-PHP) script
    /*
        uri[o.q.name] = {};
        uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
        if ($1) {uri[o.q.name][$1] = $2;}
        });
        return uri;
    */

    switch (component) {
        case 'PHP_URL_SCHEME':
            return uri.protocol;
        case 'PHP_URL_HOST':
            return uri.host;
        case 'PHP_URL_PORT':
            return uri.port;
        case 'PHP_URL_USER':
            return uri.user;
        case 'PHP_URL_PASS':
            return uri.password;
        case 'PHP_URL_PATH':
            return uri.path;
        case 'PHP_URL_QUERY':
            return uri.query;
        case 'PHP_URL_FRAGMENT':
            return uri.anchor;
        default:
            var retArr = {};
            if (uri.protocol !== '') {retArr.scheme=uri.protocol;}
            if (uri.host !== '') {retArr.host=uri.host;}
            if (uri.port !== '') {retArr.port=uri.port;}
            if (uri.user !== '') {retArr.user=uri.user;}
            if (uri.password !== '') {retArr.pass=uri.password;}
            if (uri.path !== '') {retArr.path=uri.path;}
            if (uri.query !== '') {retArr.query=uri.query;}
            if (uri.anchor !== '') {retArr.fragment=uri.anchor;}
            return retArr;
    }
}


window.i3.std.string.__base64 = {
    encodeChars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
    decodeChars: 
    [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
    -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1]
}

window.i3.std.string.btoa = function(str)
{
    if (window.btoa)
        return window.btoa(str);
        
    var out, i, len;
    var c1, c2, c3;

    len = str.length;
    i = 0;
    out = "";
    while(i < len) {
    c1 = str.charCodeAt(i++) & 0xff;
    if(i == len)
    {
        out += i3.std.string.__base64.encodeChars.charAt(c1 >> 2);
        out += i3.std.string.__base64.encodeChars.charAt((c1 & 0x3) << 4);
        out += "==";
        break;
    }
    c2 = str.charCodeAt(i++);
    if(i == len)
    {
        out += i3.std.string.__base64.encodeChars.charAt(c1 >> 2);
        out += i3.std.string.__base64.encodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
        out += i3.std.string.__base64.encodeChars.charAt((c2 & 0xF) << 2);
        out += "=";
        break;
    }
    c3 = str.charCodeAt(i++);
    out += i3.std.string.__base64.encodeChars.charAt(c1 >> 2);
    out += i3.std.string.__base64.encodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
    out += i3.std.string.__base64.encodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6));
    out += i3.std.string.__base64.encodeChars.charAt(c3 & 0x3F);
    }
    
    return out;
}

window.i3.std.string.atob = function(str)
{
    if (window.atob)
        return window.atob(str);
        
        
    var c1, c2, c3, c4;
    var i, len, out;

    len = str.length;
    i = 0;
    out = "";
    while(i < len) {
    /* c1 */
    do {
        c1 = i3.std.string.__base64.decodeChars[str.charCodeAt(i++) & 0xff];
    } while(i < len && c1 == -1);
    if(c1 == -1)
        break;

    /* c2 */
    do {
        c2 = i3.std.string.__base64.decodeChars[str.charCodeAt(i++) & 0xff];
    } while(i < len && c2 == -1);
    if(c2 == -1)
        break;

    out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));

    /* c3 */
    do {
        c3 = str.charCodeAt(i++) & 0xff;
        if(c3 == 61)
        return out;
        c3 = i3.std.string.__base64.decodeChars[c3];
    } while(i < len && c3 == -1);
    if(c3 == -1)
        break;

    out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));

    /* c4 */
    do {
        c4 = str.charCodeAt(i++) & 0xff;
        if(c4 == 61)
        return out;
        c4 = i3.std.string.__base64.decodeChars[c4];
    } while(i < len && c4 == -1);
    if(c4 == -1)
        break;
    out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
    }
    
    return out;
}
