// define constants

var REGEX_CUSTOM_FLOAT = /^\d{1,4}(\.\d{1,3}){0,1}$/; // xxxx.x | xxxx.xx | xxxx.xxx | xxxx
var REGEX_NAME = /^[\ \-\.a-zA-Z]{2,60}$/;
var REGEX_PHONE = /^[\d\ \-\+()]{4,20}$/;
var REGEX_VALUE = /^\d{1,6}(\.\d{1,2}){0,1}$/;
var REGEX_WORD_10 = /^[\w\ \-\.\|\/\[\],()]{1,10}$/;
var REGEX_WORD_30 = /^[\w\ \-\.\|\/\[\],()]{1,30}$/;
var REGEX_WORD_60 = /^[\w\ \-\.\|\/\[\],()]{1,60}$/;
var REGEX_EMAIL = /^([\w\+\-]+)(\.[\w\+\-]+)*@([\w\-]+\.)+[a-z]{2,6}$/i;
var REGEX_PASSWORD = /^.{5,}$/i;

// custom constants
var REGEX_NONEMPTY_MONETARY = /^\d{1,10}(\.\d{1,3}){0,1}$/; // xxxx.x | xxxx.xx | xxxx.xxx | xxxx

// define functiona
function range ( low, high, step ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Waldo Malqui Silva
    // *     example 1: range ( 0, 12 );
    // *     returns 1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
    // *     example 2: range( 0, 100, 10 );
    // *     returns 2: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
    // *     example 3: range( 'a', 'i' );
    // *     returns 3: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
    // *     example 4: range( 'c', 'a' );
    // *     returns 4: ['c', 'b', 'a']
 
    var matrix = [];
    var inival, endval, plus;
    var walker = step || 1;
    var chars  = false;
 
    if ( !isNaN( low ) && !isNaN( high ) ) {
        inival = low;
        endval = high;
    } else if ( isNaN( low ) && isNaN( high ) ) {
        chars = true;
        inival = low.charCodeAt( 0 );
        endval = high.charCodeAt( 0 );
    } else {
        inival = ( isNaN( low ) ? 0 : low );
        endval = ( isNaN( high ) ? 0 : high );
    }
 
    plus = ( ( inival > endval ) ? false : true );
    if ( plus ) {
        while ( inival <= endval ) {
            matrix.push( ( ( chars ) ? String.fromCharCode( inival ) : inival ) );
            inival += walker;
        }
    } else {
        while ( inival >= endval ) {
            matrix.push( ( ( chars ) ? String.fromCharCode( inival ) : inival ) );
            inival -= walker;
        }
    }
 
    return matrix;
}

function in_array(needle, haystack, argStrict) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: vlado houba
    // *     example 1: in_array('van', ['Kevin', 'van', 'Zonneveld']);
    // *     returns 1: true
    // *     example 2: in_array('vlado', {0: 'Kevin', vlado: 'van', 1: 'Zonneveld'});
    // *     returns 2: false
    // *     example 3: in_array(1, ['1', '2', '3']);
    // *     returns 3: true
    // *     example 3: in_array(1, ['1', '2', '3'], false);
    // *     returns 3: true
    // *     example 4: in_array(1, ['1', '2', '3'], true);
    // *     returns 4: false
 
    var key = '', strict = !!argStrict;
 
    if (strict) {
        for (key in haystack) {
            if (haystack[key] === needle) {
                return true;
            }
        }
    } else {
        for (key in haystack) {
            if (haystack[key] == needle) {
                return true;
            }
        }
    }
 
    return false;
}

function serialize( mixed_value ) {
    // Returns a string representation of variable (which can later be unserialized)  
    // 
    // version: 906.1807
    // discuss at: http://phpjs.org/functions/serialize
    // +   original by: Arpad Ray (mailto:arpad@php.net)
    // +   improved by: Dino
    // +   bugfixed by: Andrej Pavlovic
    // +   bugfixed by: Garagoth
    // +      input by: DtTvB (http://dt.in.th/2008-09-16.string-length-in-bytes.html)
    // +   bugfixed by: Russell Walker (http://www.nbill.co.uk/)
    // %          note: We feel the main purpose of this function should be to ease the transport of data between php & js
    // %          note: Aiming for PHP-compatibility, we have to translate objects to arrays
    // *     example 1: serialize(['Kevin', 'van', 'Zonneveld']);
    // *     returns 1: 'a:3:{i:0;s:5:"Kevin";i:1;s:3:"van";i:2;s:9:"Zonneveld";}'
    // *     example 2: serialize({firstName: 'Kevin', midName: 'van', surName: 'Zonneveld'});
    // *     returns 2: 'a:3:{s:9:"firstName";s:5:"Kevin";s:7:"midName";s:3:"van";s:7:"surName";s:9:"Zonneveld";}'
    var _getType = function( inp ) {
        var type = typeof inp, match;
        var key;
        if (type == 'object' && !inp) {
            return 'null';
        }
        if (type == "object") {
            if (!inp.constructor) {
                return 'object';
            }
            var cons = inp.constructor.toString();
            match = cons.match(/(\w+)\(/);
            if (match) {
                cons = match[1].toLowerCase();
            }
            var types = ["boolean", "number", "string", "array"];
            for (key in types) {
                if (cons == types[key]) {
                    type = types[key];
                    break;
                }
            }
        }
        return type;
    };
    var type = _getType(mixed_value);
    var val, ktype = '';
    
    switch (type) {
        case "function": 
            val = ""; 
            break;
        case "boolean":
            val = "b:" + (mixed_value ? "1" : "0");
            break;
        case "number":
            val = (Math.round(mixed_value) == mixed_value ? "i" : "d") + ":" + mixed_value;
            break;
        case "string":
            val = "s:" + encodeURIComponent(mixed_value).replace(/%../g, 'x').length + ":\"" + mixed_value + "\"";
            break;
        case "array":
        case "object":
            val = "a";
            /*
            if (type == "object") {
                var objname = mixed_value.constructor.toString().match(/(\w+)\(\)/);
                if (objname == undefined) {
                    return;
                }
                objname[1] = serialize(objname[1]);
                val = "O" + objname[1].substring(1, objname[1].length - 1);
            }
            */
            var count = 0;
            var vals = "";
            var okey;
            var key;
            for (key in mixed_value) {
                ktype = _getType(mixed_value[key]);
                if (ktype == "function") { 
                    continue; 
                }
                
                okey = (key.match(/^[0-9]+$/) ? parseInt(key, 10) : key);
                vals += serialize(okey) +
                        serialize(mixed_value[key]);
                count++;
            }
            val += ":" + count + ":{" + vals + "}";
            break;
        case "undefined": // Fall-through
        default: // if the JS object has a property which contains a null value, the string cannot be unserialized by PHP
            val = "N";
            break;
    }
    if (type != "object" && type != "array") {
        val += ";";
    }
    return val;
}

function ucfirst(str) {
    var firstLetter = str.substr(0, 1);
    return firstLetter.toUpperCase() + str.substr(1);
}


function round(number,dec_places){
//(c) Copyright 2008, Russell Walker, Netshine Software Limited. www.netshinesoftware.com
var new_number='';var i=0;number=number.toString();dec_places=dec_places*1;dec_point_pos=number.lastIndexOf(".");if(dec_point_pos==0){number="0"+number;dec_point_pos=1}if(dec_point_pos==-1||dec_point_pos==number.length-1){if(dec_places>0){new_number=number+".";for(i=0;i<dec_places;i++){new_number+="0"}return new_number}else{return number}}var existing_places=(number.length-1)-dec_point_pos;if(existing_places==dec_places){return number}if(existing_places<dec_places){new_number=number;for(i=existing_places;i<dec_places;i++){new_number+="0"}return new_number}var end_pos=(dec_point_pos*1)+dec_places;var round_up=false;if((number.charAt(end_pos+1)*1)>4){round_up=true}var digit_array=new Array();for(i=0;i<=end_pos;i++){digit_array[i]=number.charAt(i)}var stop=false;for(i=digit_array.length;i>dec_point_pos;i--){if(digit_array[i]=="."){stop=true;continue}if(round_up){digit_array[i]++;if(digit_array[i]<10){break}}else{break}if(stop){break}}for(i=0;i<=end_pos;i++){if(digit_array[i]=="."||digit_array[i]<10){new_number+=digit_array[i]}else{new_number+="0"}}if(dec_places==0){new_number=new_number.replace(".","")}return new_number}

function gup(name)
{
  //name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var results = regex.exec( window.location.href );
  if( results == null )
    return "";
  else
    return results;
}

function resetFileInputs(){
	$('input[type=file]').val('');
}

// example call validateParam('')
function validateParam(jQueryIdentifierString, validationType, errorClass)
{
	if (errorClass == undefined) errorClass = 'error-highlight';
	
	var validates = true;
	
	// default to nonempty if undefined
	if (validationType == undefined) validationType = 'nonempty';
	// convert to array
	if (typeof validationType == 'string')
		validationType = [validationType];
		
	// defaults to nonempty
	if (!in_array('empty', validationType) && !in_array('nonempty', validationType))
		validationType.push('nonempty');
	
	var value = $.trim($(jQueryIdentifierString).val());	
	
	for (key in validationType)
	{	
		if (!value)
		{
			if(validationType[key] == 'nonempty')
			{	
				validates = false;
				break;	
			}		
		}
		else
		{
			switch(validationType[key])
			{		
				case('email'):
					if (!$(jQueryIdentifierString).val().match(REGEX_EMAIL)) validates = false;
					break;	
				case('phone'):
					if (!$(jQueryIdentifierString).val().match(REGEX_PHONE)) validates = false;
					break;		
				case('password'):	
					if (!$(jQueryIdentifierString).val().match(REGEX_PASSWORD)) validates = false;
					break;			
				case('name'):	
					if (!$(jQueryIdentifierString).val().match(REGEX_NAME)) validates = false;
					break;			
				case('float'):	
					if (!$(jQueryIdentifierString).val().match(REGEX_CUSTOM_FLOAT)) validates = false;
					break;
				case('monetary'):	
					if (!$(jQueryIdentifierString).val().match(REGEX_NONEMPTY_MONETARY)) validates = false;
					break;					
			}			
		}
			
		if (validates == false) break;
	}

	
	if (!validates){
		$(jQueryIdentifierString).addClass(errorClass);
		return false;
	}
	else{
		$(jQueryIdentifierString).removeClass(errorClass);
		return true;
	}
		
	
}

function displayMessage(msg, type, fadeOut)
{
	switch(type)
	{
		case('error'):
			$('#messages').html("<p class='msg error'>"+msg+"</p>").fadeIn();
			break;
		case('success'):
			$('#messages').html("<p class='msg done'>"+msg+"</p>").fadeIn();
			break;		
		case('info'):
			$('#messages').html("<p class='msg info'>"+msg+"</p>").fadeIn();
			break;	
		case('warning'):
			$('#messages').html("<p class='msg warning'>"+msg+"</p>").fadeIn();
			break;					
	}
		
	// shift focus to top of the page
	if (!$('#top_anchor').length)
		$('body').prepend('<a href="#" id="top_anchor"></a>');
	$('#top_anchor').focus();
	
	// fade out if necessary
	if (fadeOut != undefined){
		var timeout = 4000;
		if (typeof fadeOut == 'number'){
			timeout = fadeOut;
		}
		
		setTimeout("$('#messages').fadeOut();", timeout);
	}
}

function closeMessages()
{
	$('#messages').html('');
}

function getOrderByLink(columnName)
{
	var orderBy = 'order_by='+columnName;
	var href = window.location.href;
}

// opens a pop up window and centers it on the screen
function openPopup(link, width, height, name)
{
	var left = (screen.width/2)-(width/2);
	var top = (screen.height/2)-(height/2);
	
	if (name == undefined)
		name = "new_window";
		
	window.open(link, name, 'menubar=0, status=0, location=0, resizable=1, scrollbars=1, width='+width+', height='+height+', top='+top+', left='+left);
}

// useful for generating random token to prevent caching
function getTimeMilliseconds() {
    return '' + new Date().getTime();
}

// more robust randomString
function randomString(length) {
    var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'.split('');
    
    if (! length) {
        length = Math.floor(Math.random() * chars.length);
    }
    
    var str = '';
    for (var i = 0; i < length; i++) {
        str += chars[Math.floor(Math.random() * chars.length)];
    }
    return str;
}

function getInt(val)
{
	return isNaN(parseInt(val)) ? 0 : parseInt(val);
}

function getFloat(val)
{
	return isNaN(parseFloat(val)) ? 0 : parseFloat(val);
}

