Ext.onReady(function(){
    
    Ext.grid.CheckColumn = function(config){
	Ext.apply(this, config);
	if(!this.id){
	    this.id = Ext.id();
	}
	this.renderer = this.renderer.createDelegate(this);
    };

    Ext.grid.CheckColumn.prototype ={
	init : function(grid){
	    this.grid = grid;
	    this.grid.on('render', function(){
		var view = this.grid.getView();
		view.mainBody.on('mousedown', this.onMouseDown, this);
	    }, this);
	},

	onMouseDown : function(e, t){
	    if(t.className && t.className.indexOf('x-grid3-cc-'+this.id) != -1){
		e.stopEvent();
		var index = this.grid.getView().findRowIndex(t);
		var record = this.grid.store.getAt(index);
		record.set(this.dataIndex, !record.data[this.dataIndex]);
	    }
	},

	renderer : function(v, p, record){
	    p.css += ' x-grid3-check-col-td'; 
	    return '<div class="x-grid3-check-col'+(v?'-on':'')+' x-grid3-cc-'+this.id+'">&#160;</div>';
	}
    };

    // Apply form group (thanks Jack!)
    Ext.ux.FormGroup = Ext.extend(Ext.Panel, {
	collapsible:true,
	animCollapse: false,
	titleCollapse:true,
	bodyStyle:'padding:10px;',
	hideCollapseTool: true,
	baseCls:'form-group',
	defaults:{
	    labelAlign:'top'
	}
    });
    
    Ext.ux.SimpleCombo = function(config) {
	Ext.ux.SimpleCombo.superclass.constructor.call(this, config);
    	this.store = new Ext.data.SimpleStore({
	    fields: ['Key', 'Value'],
	    data : config.data
	});
	this.displayField='Value';
	this.valueField='Key';
	this.mode='local';
	this.triggerAction='all';
	this.editable=false;
    };
    
    Ext.extend(Ext.ux.SimpleCombo, Ext.form.ComboBox, {});   
    
    // Register
    Ext.reg('formgroup', Ext.ux.FormGroup);
    Ext.reg('simplecombo', Ext.ux.SimpleCombo);

    Ext.apply(Ext.util.Format, {
	numberFormat: {
		decimalSeparator: '.',
		decimalPrecision: 2,
		groupingSeparator: ',',
		groupingSize: 3,
		currencySymbol: '$'
	},
	formatNumber: function(value, numberFormat) {
		var format = Ext.apply(Ext.apply({}, this.numberFormat), numberFormat);
		if (typeof value !== 'number') {
			value = String(value);
			if (format.currencySymbol) {
				value = value.replace(format.currencySymbol, '');
			}
			if (format.groupingSeparator) {
				value = value.replace(new RegExp(format.groupingSeparator, 'g'), '');
			}
			if (format.decimalSeparator !== '.') {
				value = value.replace(format.decimalSeparator, '.');
			}
			value = parseFloat(value);
		}
		var neg = value < 0;
		value = Math.abs(value).toFixed(format.decimalPrecision);
		var i = value.indexOf('.');
		if (i >= 0) {
			if (format.decimalSeparator !== '.') {
				value = value.slice(0, i) + format.decimalSeparator + value.slice(i + 1);
			}
		} else {
			i = value.length;
		}
		if (format.groupingSeparator) {
			while (i > format.groupingSize) {
				i -= format.groupingSize;
				value = value.slice(0, i) + format.groupingSeparator + value.slice(i);
			}
		}
		if (format.currencySymbol) {
			value = format.currencySymbol + value;
		}
		if (neg) {
			value = '-' + value;
		}
		return value;
	}
    });


    String.prototype.utf8_decode = function(s)
    {
       return decodeURIComponent( escape( s ) );
    }

    String.prototype.utf8_encode = function(s)
    {
	     return unescape( encodeURIComponent( s ) );
    }

    Number.prototype.truncate = function(n)
    {
	    return Math.round(this * Math.pow(10, n)) / Math.pow(10, n);
    }
     
    Ext.ux.currencyField = function(config) {
	    this.format = config.format || "£#,###.##"; //us format;
	    Ext.ux.currencyField.superclass.constructor.call(this, config);
	    
	    this.on('focus',this._onFocus);
	    this.on('blur',this._onBlur);
	    this.on('render',this._onRender);
	this.on('change',this._onChange,this);   
	    this.oValue=config.value || 0;
	    
    }

    Ext.extend(Ext.ux.currencyField, Ext.form.NumberField, {
       format:"",
       oValue:0,
       _onChange:function(f,n,o){
	   this.oValue = n;
	   this.setRawValue(this.formatter(n));
       },
       getValue:function(){
	     return this.oValue;
       },
       _onRender:function(cmp){
		    this.setRawValue(this.formatter(this.oValue));
       },   
       formatter:function(value){
	      var prefix = '';
	      var decimals = '';
	      var millars = '';
	      var ndecimals = 0;
		    
	      var s = this.format.substring(1);
	      
	      for(var i=0; i < this.format.length; i++)
	      {
		    if(this.format.charAt(i) != '#')
		    {
			    prefix = prefix + this.format.charAt(i);			
		    }else
			    break;
	      }
	      
	      s =  this.format.substring(prefix.length);
	      
	      for(var i=0; i < s.length; i++)
		    if(s.charAt(i) != '#')
		    {
			    millars = s.charAt(i);
			    s = s.substring(i+1);
			    break;
		    }
	      
	      for(var i=0; i < s.length; i++)
		    if(s.charAt(i) != '#')
		    {
			    decimals = s.charAt(i);
			    ndecimals = s.substring(i+1).length;

			    break;
		    }

	      var n = new Number(value);
	      
	      ip = Math.floor(n);
	      
	      var dp = n - ip; 
	    
	      dp = Math.round(dp*Math.pow(10,ndecimals)); 
		      
	      var regex  = new RegExp('(-?[0-9]+)([0-9]{3})');
	      ip = ip+'';
	      while(regex.test(ip))		
		    ip = ip.replace(regex, '$1' + millars + '$2');
     
	      ip = prefix+ip;
	      if(ndecimals > 0)
	       ip = ip+decimals+dp;  
		      
	      return ip;
       },
       _onBlur:function(field){
		    this.oValue=field.getRawValue();
		    field.setRawValue(this.formatter(this.oValue));
       },
       _onFocus:function(field){
	       field.setRawValue(this.oValue);
       }
    });
    
    Ext.reg('currencyfield', Ext.ux.currencyField);

    Ext.form.VTypes.name			=	function(v){return Ext.form.VTypes.nameVal.test(v);};
    Ext.form.VTypes.nameVal 			= 	/^([a-z]|[A-Z]|'|\-| )+$/;
    Ext.form.VTypes.nameMask 			= 	/[a-z|A-Z|\-|'| ]/;
    Ext.form.VTypes.nameText 			= 	'Invalid name, may only alphanumeric characters, - or \'';
    
    Ext.form.VTypes.address			=	function(v){return Ext.form.VTypes.addressVal.test(v);};
    Ext.form.VTypes.addressVal 			= 	/^([0-9]|[a-z]|[A-Z]|'|\-| )+$/;
    Ext.form.VTypes.addressMask 		= 	/[0-9]|[a-z|A-Z|\-|'| ]/;
    Ext.form.VTypes.addressText 		= 	'Invalid address, may only alphanumeric characters, - or \'';
    
    Ext.form.VTypes.ukphone			=	function(v){return Ext.form.VTypes.ukphoneVal.test(v);};
    Ext.form.VTypes.ukphoneVal 			= 	/^[0][1|2|7|8]\d{8,9}$/;
    Ext.form.VTypes.ukphoneMask 		= 	/[\d\-]/;
    Ext.form.VTypes.ukphoneText 		= 	'Invalid UK phone number. Valid examples would be 07000 123123 or 0845 9170000';
    
    
    Ext.form.VTypes.money			=	function(v){return Ext.form.VTypes.percentageVal.test(v);};
    Ext.form.VTypes.moneyVal	 		= 	/^[\d]{1,2}(\.[\d]{1,2})?$|^100$/;
    Ext.form.VTypes.moneyMask	 		= 	/[\d.]/;
    Ext.form.VTypes.percentageText 		= 	'This field must be a percentage between 0.00 and 100.00';
    
    Ext.form.VTypes.percentage			=	function(v){return Ext.form.VTypes.percentageVal.test(v);};
    Ext.form.VTypes.percentageVal 		= 	/^[\d]{1,2}(\.[\d]{1,2})?$|^100$/;
    Ext.form.VTypes.percentageMask 		= 	/[\d.]/;
    Ext.form.VTypes.percentageText 		= 	'This field must be a percentage between 0.00 and 100.00';
    
    Ext.form.VTypes.username			=	function(v){return Ext.form.VTypes.usernameVal.test(v);};
    Ext.form.VTypes.usernameVal 		= 	/^(\w){6,16}$/;
    Ext.form.VTypes.usernameMask 		= 	/[\w.]/;
    Ext.form.VTypes.usernameText 		= 	'Invalid username, must only contain alphanumeric characters and be between 6-16 characters in length.';
    
    Ext.form.VTypes.password			=	function(v){return Ext.form.VTypes.passwordVal.test(v);};
    Ext.form.VTypes.passwordVal 		= 	/^(\w){6,32}$/;
    Ext.form.VTypes.passwordMask 		= 	/[\w.]/;
    Ext.form.VTypes.passwordText 		= 	'Invalid password, must be between 6-32 characters in length.';
    
    Ext.form.VTypes.clientname			=	function(v){return Ext.form.VTypes.clientnameVal.test(v);};
    Ext.form.VTypes.clientnameVal 		= 	/^([a-z]|[A-Z]|'|\-| ){2,32}$/;
    Ext.form.VTypes.clientnameMask 		= 	/[a-z|A-Z|\-| ']/;
    Ext.form.VTypes.clientnameText 		= 	'Invalid client name, may only alphanumeric characters, - or \' and must be between 2-32 characters in length';
    
    Ext.form.VTypes.codename			=	function(v){return Ext.form.VTypes.codenameVal.test(v);};
    Ext.form.VTypes.codenameVal 		= 	/^([a-z]|[A-Z]){2,8}$/;
    Ext.form.VTypes.codenameMask 		= 	/[a-z|A-Z]/;
    Ext.form.VTypes.codenameText 		= 	'Invalid client name, may only alphanumeric characters and must be between 2-8 characters in length';
    
    Ext.form.VTypes.ipVal 		= 	/^([1-9][0-9]{0,1}|1[013-9][0-9]|12[0-689]|2[01][0-9]|22[0-3])([.]([1-9]{0,1}[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])){2}[.]([1-9][0-9]{0,1}|1[0-9]{2}|2[0-4][0-9]|25[0-4])$/;
    Ext.form.VTypes.ipMask		=	/[.0-9]/;
    Ext.form.VTypes.ipText		=	"Invalid IP address, must be within the range of 1.0.0.1 - 223.255.255.254 excluding 127.x.x.x";
    Ext.form.VTypes.ip			=	function(v){return Ext.form.VTypes.ipVal.test(v);};
    
    Ext.form.VTypes.portVal		=	/^(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/;
    Ext.form.VTypes.portMask 		=	/[0-9]/;
    Ext.form.VTypes.portText 		=	"Invalid port number, must be within the range of 0-65535";
    Ext.form.VTypes.port 		=	function(v){return Ext.form.VTypes.portVal.test(v);};

    Ext.form.VTypes.postcodeVal		=	/(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW]) {0,1}[0-9][ABD-HJLNP-UW-Z]{2})/i;
    Ext.form.VTypes.postcodeMask 	=	/[0-9]|[a-z]|[A-Z]/;
    Ext.form.VTypes.postcodeText 	=	"Sorry, that doesn't appear to be a valid postcode";
    Ext.form.VTypes.postcode 		=	function(v){return Ext.form.VTypes.postcodeVal.test(v);};
});

function displaySimpleError(msg,callback) {
    Ext.MessageBox.show({
       title		:	'Error',
       msg		:	msg,
       buttons		:	Ext.MessageBox.OK,
       width		:	400,
       animEl		:	'mb9',
       fn		:	callback,
       icon		:	Ext.MessageBox.ERROR
    });
    Ext.Msg.getDialog().dd.lock();
}


function displaySimpleOk(msg,callback) {
    Ext.MessageBox.show({
       title: 'Request Successful',
       msg: msg,
       buttons: Ext.MessageBox.OK,
       width:400,
       animEl: 'mb9',
       fn: callback,
       icon: Ext.MessageBox.INFO
    });
}

function joinObjects(objs) {
    obj = new Object();
    for(x=0;x<objs.length;x++) {
    	for (attrname in objs[x]) { obj[attrname] = objs[x][attrname]; }
    }
    return obj
}

Array.prototype.has = function(value) {
    return (this.value!==undefined)
};

function is_string(input){
    return typeof(input)=='string';
}


function checkFileExtension(file,type) {
    try {
	// Define file types
	types = new Object({
	    'picture'	: new Object({
		'jpg'		:	true,
		'jpeg'		:	true,
		'png'		:	true,
		'gif'		:	true
	    })
	});
	
	// Check if the file is a string
	if (!is_string(file)) { return false; }
	
	// Check filename
	if (substr_count(file,'.')==0) { return false; }
	
	// Check if type is valid
	if (!property_exists(types,type)) { return false; }
	
	// Split filename
	file = file.split(".");
	
	// Grab file extention
	return property_exists(types[type],file[(file.length-1)])
    }
    catch (Exception) {
    	return false;
    }
}


// {{{ base64_decode
function base64_decode( data ) {
    // Decodes data encoded with MIME base64
    // 
    // +    discuss at: http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_base64_decode/
    // +       version: 810.819
    // +   original by: Tyler Akins (http://rumkin.com)
    // +   improved by: Thunder.m
    // +      input by: Aman Gupta
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: Onno Marsman
    // -    depends on: utf8_decode
    // *     example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
    // *     returns 1: 'Kevin van Zonneveld'

    // mozilla has this native
    // - but breaks in 2.0.0.12!
    //if (typeof window['btoa'] == 'function') {
    //    return btoa(data);
    //}

    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var o1, o2, o3, h1, h2, h3, h4, bits, i = ac = 0, dec = "", tmp_arr = [];

    data += '';

    do {  // unpack four hexets into three octets using index points in b64
        h1 = b64.indexOf(data.charAt(i++));
        h2 = b64.indexOf(data.charAt(i++));
        h3 = b64.indexOf(data.charAt(i++));
        h4 = b64.indexOf(data.charAt(i++));

        bits = h1<<18 | h2<<12 | h3<<6 | h4;

        o1 = bits>>16 & 0xff;
        o2 = bits>>8 & 0xff;
        o3 = bits & 0xff;

        if (h3 == 64) {
            tmp_arr[ac++] = String.fromCharCode(o1);
        } else if (h4 == 64) {
            tmp_arr[ac++] = String.fromCharCode(o1, o2);
        } else {
            tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
        }
    } while (i < data.length);

    dec = tmp_arr.join('');
    dec = utf8_decode(dec);

    return dec;
}// }}}

// {{{ base64_encode
function base64_encode( data ) {
    // Encodes data with MIME base64
    // 
    // +    discuss at: http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_base64_encode/
    // +       version: 809.522
    // +   original by: Tyler Akins (http://rumkin.com)
    // +   improved by: Bayron Guevara
    // +   improved by: Thunder.m
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)        
    // -    depends on: utf8_encode
    // *     example 1: base64_encode('Kevin van Zonneveld');
    // *     returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='

    // mozilla has this native
    // - but breaks in 2.0.0.12!
    //if (typeof window['atob'] == 'function') {
    //    return atob(data);
    //}
        
    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var o1, o2, o3, h1, h2, h3, h4, bits, i = ac = 0, enc="", tmp_arr = [];
    data = utf8_encode(data);
    
    do { // pack three octets into four hexets
        o1 = data.charCodeAt(i++);
        o2 = data.charCodeAt(i++);
        o3 = data.charCodeAt(i++);

        bits = o1<<16 | o2<<8 | o3;

        h1 = bits>>18 & 0x3f;
        h2 = bits>>12 & 0x3f;
        h3 = bits>>6 & 0x3f;
        h4 = bits & 0x3f;

        // use hexets to index into b64, and append result to encoded string
        tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
    } while (i < data.length);
    
    enc = tmp_arr.join('');
    
    switch( data.length % 3 ){
        case 1:
            enc = enc.slice(0, -2) + '==';
        break;
        case 2:
            enc = enc.slice(0, -1) + '=';
        break;
    }

    return enc;
}// }}}


// {{{ utf8_decode
function utf8_decode ( str_data ) {
    // Converts a string with ISO-8859-1 characters encoded with UTF-8   to single-byte
    // ISO-8859-1
    // 
    // +    discuss at: http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_utf8_decode/
    // +       version: 810.621
    // +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
    // +      input by: Aman Gupta
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Norman "zEh" Fuchs
    // +   bugfixed by: hitwork
    // +   bugfixed by: Onno Marsman
    // *     example 1: utf8_decode('Kevin van Zonneveld');
    // *     returns 1: 'Kevin van Zonneveld'

    var tmp_arr = [], i = ac = c1 = c2 = c3 = 0;

    str_data += '';

    while ( i < str_data.length ) {
        c1 = str_data.charCodeAt(i);
        if (c1 < 128) {
            tmp_arr[ac++] = String.fromCharCode(c1);
            i++;
        } else if ((c1 > 191) && (c1 < 224)) {
            c2 = str_data.charCodeAt(i+1);
            tmp_arr[ac++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
            i += 2;
        } else {
            c2 = str_data.charCodeAt(i+1);
            c3 = str_data.charCodeAt(i+2);
            tmp_arr[ac++] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
            i += 3;
        }
    }

    return tmp_arr.join('');
}// }}}

// {{{ utf8_encode
function utf8_encode ( string ) {
    // Encodes an ISO-8859-1 string to UTF-8
    // 
    // +    discuss at: http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_utf8_encode/
    // +       version: 811.1414
    // +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: sowberry
    // +    tweaked by: Jack
    // +   bugfixed by: Onno Marsman
    // +   improved by: Yves Sucaet
    // +   bugfixed by: Onno Marsman
    // *     example 1: utf8_encode('Kevin van Zonneveld');
    // *     returns 1: 'Kevin van Zonneveld'

    string = (string+'').replace(/\r\n/g, "\n").replace(/\r/g, "\n");

    var utftext = "";
    var start, end;
    var stringl = 0;

    start = end = 0;
    stringl = string.length;
    for (var n = 0; n < stringl; n++) {
        var c1 = string.charCodeAt(n);
        var enc = null;

        if (c1 < 128) {
            end++;
        } else if((c1 > 127) && (c1 < 2048)) {
            enc = String.fromCharCode((c1 >> 6) | 192) + String.fromCharCode((c1 & 63) | 128);
        } else {
            enc = String.fromCharCode((c1 >> 12) | 224) + String.fromCharCode(((c1 >> 6) & 63) | 128) + String.fromCharCode((c1 & 63) | 128);
        }
        if (enc != null) {
            if (end > start) {
                utftext += string.substring(start, end);
            }
            utftext += enc;
            start = end = n+1;
        }
    }

    if (end > start) {
        utftext += string.substring(start, string.length);
    }

    return utftext;
}// }}}

