Ext.namespace('Yext');

Yext.util = {
	/* 
	 * Handles responseText returned by XmlHttp request.
	 * Returns eval'ed value if no error occurs.
	 * Returns false if error was found in responeseText
	 */
	responseTextHandler: function(res){
		var ret = false;

		if(!res || res.length==0 || res=='null'){ 
			alert('Failed to initialize application. Sorry');
		}else{	
			eval("var res = "+res);
			if(res.error){
				alert(res.error);
			}else if(res.redirect){
				location.href = res.redirect+'?src='+location.href;
			}else if(res.login){
				new Yext.util.authorize({
					url: res.login,
					mode: 'in'
				});
			}else{
				ret = res;
			}
		}
	
		return ret;
	},
	
	/*
	 * Wrapper to Ext.get().
	 * 
	 * Returns Ext.Element object returned by Ext.get if DOM with given id exists
	 * If specified DOM does not exist, this method will create a DOM with Ext.DomHelper and
	 * return Ext.Element of it. New DOM will be created as a direct child of body element.
	 * 
	 * You can specify configurations for DOM by giving a second argument 
	 * (such as tag, class, etc)
	 */
	get: function(id){
		var el = Ext.get(id);
		if(!el){
			var cfg = arguments.length>1?arguments[1]:{};
			var tag = cfg.tag?cfg.tag:'div';
			el = Ext.DomHelper.append(Ext.getBody(),{
				id:id,
				tag:tag
			},true); // true to return Ext.Element
		}
		return el;
	},
	
	createMap:	function(opt){
		if(!opt.id){ return null; }
		
		var map = new GMap2(Yext.util.get(opt.id).dom);
		
		if(opt.continuousZoom !== false){ map.enableContinuousZoom() };
		if(opt.scrollWheelZoom !== false){ map.enableScrollWheelZoom(); }
		if(opt.smallMapControl === true) { map.addControl(new Gmap.SmallMapControl()); }
		
		var zoom = opt.zoom?opt.zoom:1;
		if(opt.lat && opt.lng){
			map.setCenter(new GLatLng(opt.lat,opt.lng),zoom);
		}else{
			map.setCenter(new GLatLng(0,0),zoom);			
		}
		
		return map;
	},
	
	/*
	 * Handles error with pre-assigned error code
	 * Error message can be passed as a second argument
	 */
	error: function(code){
		var msg = false;
		var err = '';
		
		if(arguments.length>1){ msg = arguments[1]; }
		
		switch(code){
			case 'NO_ARGS':
			case 'NO_AUTH':
			case 'AJAX_FAIL':
			case 'NO_PARTS':
			default:
				err = 'ERROR:'+code;
		}
		
		alert(err + (msg?':'+msg:''));
	},
	
	generateComponent: function(type, cfg){
		return Yext.util.components[type](cfg);		
	},
	
	generateComponents: function(cfg){
		var ret = [];
		var widgets = [
			'file_field',
			'password_field',
			'checkbox',
			'radiobtn',
			'text_field',
			'number_field',
			'date_field',
			'combo_field'
		];
		
		for(var i=0; i < widgets.length; i++){
			var w = widgets[i];
			if(cfg[w]){
				for(var j=0; j < cfg[w].length; j++){
					var p = cfg[w][j].params;
					var n = p.name;					
					ret[n] = Yext.util.generateComponent(w,p);
					if(w=='date_field'){
						ret[n].isDateField = true;
					}
				}
			}
		}
	
		ret.getValues = function(){
			var values = [];
			values.names = [];
			for(var i in ret){
				if(i!='getValues' && i!='remove'){ 
					values[i] = ret[i].getValue();
				}
			}						
			return values;
		}
		
		return ret;
	},	
	
	generateFormRows: function(cmps,cfg){
		var ret = [];
		if(typeof cfg != 'object' || cfg.length==0){ return ret; }
		
		for(var i=0; i<cfg.length; i++){
			var row = cfg[i];
			
			if(row.title){
				var row_title = {html: cfg[i].title};
				ret.push(row_title);
			}
			
			if(row.value.type=='table' && row.value.items.length>0){
				var row_value = {
					layout:			row.value.type, 
					layoutConfig:	{columns:row.value.columns},
					items: 			[]
				};
					
				for(var j=0; j<row.value.items.length; j++){
					var item = row.value.items[j];
					if(item.type=='items'){
						var c = {items: []};
						for(var k=0; k<item.items.length; k++){
							c.items.push(cmps[item.items[k]]);
						}
						row_value.items.push(c);
					}if(item.type=='html'){
						row_value.items.push({html:item.value});
					}
				}
				ret.push(row_value);
			}
		}
		return ret;
	},

	components:{
		combo_proxy: function(cfg){
			if(cfg.type=='http' && cfg.url){
				var ret = new Ext.data.HttpProxy({url: cfg.url});
				return ret;
			}else{
				return ret = new Ext.data.MemoryProxy(cfg.data);
			}
		},

		combo_store: function(cfg){ return new Ext.data.Store({
			fields: ['option', 'option_title'],
				proxy:	Yext.util.components.combo_proxy(cfg.proxy?cfg.proxy:''),
				reader:	Yext.util.components.combo_reader()
			});
		},

		combo_reader:	function(){ return new Ext.data.JsonReader({fields:[
				{name: 'option', mapping: 'id'},
				{name: 'option_title', mapping: 'name'}
			],root:'result',totalProperty:'total'});
		},

		combo_field: function(cfg){ 
			var ret = new Ext.form.ComboBox({
				fieldLabel	:	cfg.lbl?cfg.lbl:'',
				hideLabel	: cfg.lbl?false:true,
	   			allowBlank	:	cfg.blank!==false?true:false,
		    	store: Yext.util.components.combo_store(cfg.store?cfg.store:''),
		    	value: cfg.ini?cfg.ini:'',
		    	displayField:'option_title',
		    	valueField:'option',
		    	mode: 'local',
		    	triggerAction: 'all',
		    	readOnly: true,
		    	name: cfg.name?cfg.name:'',
		    	width: cfg.width?cfg.width:'auto',
	    		selectOnFocus:true
			});
		
			if(cfg.store.proxy.data){
				ret.store.load();
			}
			return ret;	
		},

		hidden_field: function(cfg){ return new Ext.form.DateField({
				name		:	cfg.name?cfg.name:'',
	   			id			:	cfg.name?cfg.name:''
			});	
		},
					
		date_field: function(cfg){ return new Ext.form.DateField({
				fieldLabel	:	cfg.lbl?cfg.lbl:'',
				hideLabel	:	cfg.lbl?false:true,
	   			allowBlank	:	cfg.blank!==false?true:false,
	    		readOnly: false
			});	
		},
	
		text_field:	function(cfg){ return new Ext.form.TextField({
				fieldLabel	:	cfg.lbl?cfg.lbl:'',
				hideLabel	:	cfg.lbl?false:true,
				name		:	cfg.name?cfg.name:'',
	   			id			:	cfg.name?cfg.name:'',
	   			width		:	cfg.width?cfg.width:'auto',
	   			maxLength	:	cfg.max?cfg.max:Number.MAX_VALUE,
	   			allowBlank	:	cfg.blank!==false?true:false,
	   			inputType	:	cfg.type?cfg.type:'text'
			});
		},

		file_field:	function(cfg){
			cfg.type = 'file';
			return Yext.util.components.text_field(cfg);
		},
	
		password_field:	function(cfg){
			cfg.type = 'password';
			return Yext.util.components.text_field(cfg);
		},

		number_field:	function(cfg){ return new Ext.form.NumberField({
				fieldLabel	:	cfg.lbl?cfg.lbl:'',
				hideLabel	:	cfg.lbl?false:true,
				name		:	cfg.name?cfg.name:'',
	   			id			:	cfg.name?cfg.name:'',
	   			allowBlank	:	cfg.blank!==false?true:false,
	   			allowDecimals:  cfg.precision?true:false,
	   			decimalPrecision: cfg.precision?cfg.precision:2,
	   			width		:	cfg.width?cfg.width:'auto'
			});
		},

		checkbox:	function(cfg){ return new Ext.form.Checkbox({
				fieldLabel	: cfg.lbl?cfg.lbl:'',
				hideLabel	: cfg.lbl?false:true,
				boxLabel	: cfg.blbl?cfg.blbl:'',
				name		:	cfg.name?cfg.name:'',
	   			id			:	cfg.name?cfg.name:''
			});
		},

		radiobtn:	function(cfg){ return new Ext.form.Radio({
				fieldLabel	: cfg.lbl?cfg.lbl:'',
				hideLabel	: cfg.lbl?false:true,
				boxLabel	: cfg.blbl?cfg.blbl:'',
				name		: cfg.gname?cfg.gname:'',
	   			id			: cfg.name?cfg.name:'',
				value		: cfg.value?cfg.value:'',
				checked		: cfg.checked?true:false
			});
		}
	}
};

Yext.util.authorize = function(){
	var opt = arguments[0];	
	if(!opt || !opt.url || !opt.mode){ 
		Yext.util.error('NO_ARGS','No url/mode is given');
		return;
	}else if(opt.mode != 'in' && opt.mode != 'out'){
		Yext.util.error('INVALID_MODE','Invalid mode is given');
		return;		
	}
	
	this.panel = null;
	this.url = opt.url;	
	this.ctrl = 'yext_auth';
	this.observers = [];
	this.components = {};
	
	this.conn = new Ext.data.Connection({
		url: this.url,
		disableCaching: true,
		method: 'POST',
		autoAbort: true,
		extraParams: { out_format: 'json', ctrl: this.ctrl }
	});
	
	if(opt.mode == 'in'){
		this.login();
	}else if(opt.mode == 'out'){
		this.logout();
	}
};

Yext.util.authorize.prototype = {
	login_handler:	function(user,pass){
		this.conn.request({
			params	:	{
				action	: Yext.cons.ACTIONS.LOGIN,
				name	: user,
				password: pass
			},
			scope	:	this,
			callback:	function(o,s,r){
				if(s){
					var res = Yext.util.responseTextHandler(r.responseText);
					if(res){				
						if(!res.status){
							Ext.MessageBox.alert('Login Failed',res.msg);
						}else{
							var exp = new Date();
							exp.setTime(Number(res.cookie.expire)*1000);
							var cp = new Ext.state.CookieProvider({expire: exp});
							cp.set(res.cookie.name,res.cookie.value);
							this.window.close();
							location.href = location.href;
						}
					}
				}							
			}	
		});		
	},

	logout_handler:	function(){		
		this.conn.request({
			params	:	{
				action	: Yext.cons.ACTIONS.LOGOUT
			},
			scope	:	this,
			callback:	function(o,s,r){
				if(s){
					var res = Yext.util.responseTextHandler(r.responseText);
					if(res){				
						if(!res.status){
							Ext.MessageBox.alert('Logout Failed',res.msg);
						}else{
							location.href = location.href;
						}
					}
				}							
			}	
		});		
	},
	
	login: function(){
	    var action_button = new Ext.Button({
			text	:	'Login',
			scope	:	this,
			handler	:	function(){
				this.login_handler(name_field.getValue(),pass_field.getValue());
			}		
	    });

	    var cancel_button = new Ext.Button({
			text	:	'キャンセル',
			scope	:	this,
			handler	:	function(){
				this.window.close();
			}
		});		

		var name_field = 	new Ext.form.TextField({
			fieldLabel	:	'Username',
			hideLabel	:	false,
			name		:	'name',
   			allowBlank	:	false,
   			inputType	:	'text'
		});

		var pass_field = 	new Ext.form.TextField({
			fieldLabel	:	'Password',
			hideLabel	:	false,
			name		:	'password',
   			allowBlank	:	false,
   			inputType	:	'password'
		});
		
		var login_form = new Ext.Window({
			title	:	'Login',
			layout:'fit',
            closeAction:'hide',
            width: 450,
            autoHeight: true,
            plain: true,
            modal: true,
            items: new Ext.form.FormPanel({
				frame		:	true,
				autoHeight	:	true,
				width		:	400,
	   			items		:	[name_field,pass_field]	
	   		}),
	   		buttonAlign: 'center',
	   		buttons: [action_button, cancel_button]
		});
													
		this.window = login_form;
		login_form.show();			
	},
	
	logout: function(){
		Ext.Msg.confirm('Logout','Logout?',function(id){
			if(id=='yes'){ this.logout_handler(); }
		},this);
	}
};

// Constants
Yext.cons = {
	ACTIONS: {
		INIT		:	'init',
		SHOW		:	'show',
		UPDATE		:	'update',
		DELETE		:	'delete',
		CREATE		:	'create',
		UPLOAD		:	'upload',
		DOWNLOAD	:	'download',
		LOGIN		:	'login',
		LOGOUT		:	'logout'
	}
};

