
/*global Ext, window */
/*jslint confusion: true, while: true, sloppy: true, forin: true */

// Ensure acms
var acms = acms || { };

acms.strings = acms.strings || { };

acms.ls = function(key) {
	return acms.strings[key] === undefined ? key : acms.strings[key];
};

acms.Msg = acms.Msg || { };
acms.Msg.show = function (title, msg, icon, fn) {
	return Ext.Msg.show({
		title : title,
		msg   : msg,
		icon  : icon,
		buttons : Ext.Msg.OK,
		modal : true,
		fn    : fn
	});
};
acms.Msg.info = function (title, msg, fn) {
	return acms.Msg.show(title, msg, Ext.Msg.INFO, fn);
};
acms.Msg.error = function (title, msg, fn) {
	return acms.Msg.show(title, msg, Ext.Msg.ERROR, fn);
};

acms.Fun = acms.Fun || { };
acms.Fun.getActionData = function (action) {
	var data;
	
	if (action.response && action.response.responseText) {
		data = Ext.decode(action.response.responseText);
	} else {
		data = { };
	}
	return data;
};
acms.Fun.showFailureMsg = function (action, strings, fn) {
	var s    = strings === undefined ? { } : strings,
	    data = acms.Fun.getActionData(action);
	
	switch (action.failureType) {
		case Ext.form.action.Action.CLIENT_INVALID:
			data.message = s.CLIENT_INVALID || 'Hibás vagy kitöltetlen mezők!';
			break;
		case Ext.form.action.Action.LOAD_FAILURE:
			data.message = s.LOAD_FAILURE || 'Rossz szerver-válasz!';
			break;
	}
	
	acms.Msg.error(data.title || 'Sikertelen', data.message, fn);
};

acms.Fun.createCondition = function(field, value, rel) {
	return {
		ClassName : '.data.SimpleCondition',
		Field : field,
		Pattern : {
			ClassName : '.data.Pattern',
			Value : value,
			Relation : rel
		}
	};
};

acms.Fun.existsCondition = function (foreign, c) {
	return {
		ClassName : '.data.ExistsCondition',
		ForeignEntity : foreign,
		Condition : c
	};
};

acms.Fun.joinCondition = function (c1,c2,rel) {
	var result;
	if (c1 === null) {
		result = c2;
	} else {
		if (c2 === null) {
			result = c1;
		} else {
			result = {
				ClassName : '.data.JointCondition',
				Condition1 : c1,
				Condition2 : c2,
				Relation : rel
			};
		}
	}
	return result;
};

(function () {
	var callFun = function(arr, scope, args) {
		var f, result;
		if (arr.length === 1) {
			f = scope[arr[0]];
			if (Ext.isFunction(f)) {
				result = f.apply(scope, args);
			} else {
				throw acms.createException(arr[0] + ' is not a function!');
			}
		} else {
			result = callFun(arr.slice(1), scope[arr[0]], args);
		}
		return result;
	};

	acms.Fun.callFun = function (fun, args) {
		var result;
	
		if (args === undefined || args === null) {
			args = [];
		}
		
		if (fun.indexOf('.') !== -1) {
			result = callFun(fun.split('.'), window, args);
		} else {
			result = callFun([fun], window, args);
		}
		return result;
	};
}());

acms.FTypes = acms.FTypes || { };
acms.FTypes.Cancel = 'Cancel';

acms.Fun.createFormWindow = function(cfg) {
	var scope = {
		window_id : Ext.id(),
		form_id : Ext.id(),
		cfg : cfg
	},
	    parseActionResponse = function (action) {
		var data;

		if (action.response && action.response.responseText) {
			data = Ext.decode(action.response.responseText);
		} else {
			data = { };
		}
		return data;
	};
	
	// Default on success handler
	scope.success = function (form, action) {
		var data = parseActionResponse(action);
		
		scope.msgBox = Ext.Msg.show({
			title   : acms.ls('success'),
			msg     : data.message || 'Saved successfully!',
			buttons : Ext.Msg.OK,
			icon    : Ext.Msg.INFO,
			modal   : true
		});
		
		scope.window.destroy();
		
		if (Ext.isFunction(scope.cfg.success)) {
			scope.cfg.success.call(scope.cfg.scope !== undefined ? scope.cfg.scope : scope, form, action, data);
		}
	};
	
	// default on failure handler
	scope.failure = function (form, action) {
		var str, data = { };
	
		switch (action.failureType) {
			case Ext.form.action.Action.CLIENT_INVALID:
				data.message = acms.ls('CLIENT_INVALID');
				break;
			case Ext.form.action.Action.CONNECT_FAILURE:
				data = parseActionResponse(action);
				break;
			case Ext.form.action.Action.LOAD_FAILURE:
				data.message = 'Invalid response!';
				break;
			case Ext.form.action.Action.SERVER_INVALID:
				data = parseActionResponse(action);
				break;
		}
		scope.msgBox = Ext.Msg.show({
			title   : acms.ls('ERROR'),
			msg     : data.message,
			buttons : Ext.Msg.OK,
			icon    : Ext.Msg.ERROR,
			modal   : true
		});
		
		if (Ext.isFunction(scope.cfg.failure)) {
			scope.cfg.failure.call(scope.cfg.scope !== undefined ? scope.cfg.scope : scope, form, action, data);
		}
	};
	
	scope.window = Ext.create('Ext.window.Window',{
		modal  : true,
		id     : scope.window_id,
		layout : 'fit',
		y      : 100,
		width  : cfg.width || 500,
		title  : cfg.title || '',
		items  : [{
			xtype : 'form',
			id    : scope.form_id,
			listeners : {
				afterrender : function(comp) {
					scope.panel = comp;
					scope.form  = comp.getForm();
					comp.items.each(function(item) {
						var b = item.isDisabled() || item.isHidden();
						if (!b) {
							item.focus();
						}
						return b;
					});
					if (scope.cfg.Phones !== undefined) {
						(function() {
							var wiredPhone  = Ext.ComponentMgr.get(scope.cfg.Phones.Wired),
							    mobilePhone = Ext.ComponentMgr.get(scope.cfg.Phones.Mobile),
							    whichPhone  = Ext.ComponentMgr.get(scope.cfg.Phones.Which);
							
							if (wiredPhone && mobilePhone && whichPhone) {
								wiredPhone.on('keypress', function(comp) {
									if (comp.validate() === true && comp.getValue().length > 0) {
										if (this.validate() === true && this.getValue().length > 0) {
											whichPhone.setDisabled(false);
										} else {
											whichPhone.setDisabled(true);
											whichPhone.setValue('Wired');
										}
									} else {
										whichPhone.setDisabled(true);
										whichPhone.setValue('Mobile');
									}
								}, mobilePhone);
								
								mobilePhone.on('keypress', function(comp) {
									if (comp.validate() === true) {
										if (this.validate() === true) {
											whichPhone.setDisabled(false);
										} else {
											whichPhone.setDisabled(true);
											whichPhone.setValue('Mobile');
										}
									} else {
										whichPhone.setDisabled(true);
										whichPhone.setValue('Wired');
									}
								}, wiredPhone);
							}
						}());
					} // if (scope.cfg.Phones !== undefined)
					if (scope.cfg.afterrender !== undefined) {
						if (Ext.isFunction(scope.cfg.afterrender)) {
							scope.cfg.afterrender.call(scope);
						}
					}
				}
			},
			bodyPadding : 20,
			items : cfg.items,
			buttons : (function() {
				var buttons = cfg.buttons;
				Ext.Array.each(buttons, function(item) {
					if (item.ftype === acms.FTypes.Cancel) {
						item.text    = acms.ls('CANCEL');
						item.handler = function() {
							this.window.destroy();
						};
					}
					item.scope = scope;
				});
				return buttons;
			}())
		}]
	});
	return scope;
};

acms.C = acms.C || { };
acms.C.Initialized = 'initialized';

acms.field = acms.field || { };

Ext.require([
	'Ext.form.Panel',
	'Ext.form.field.*',
	'Ext.form.action.*'
]);

Ext.onReady(function() {
	var simplify = function(records) {
		var i,
		    record,
		    key;

		for (i in records) {
			if (Ext.isNumeric(i)) {
				record = records[i].data;
				for (key in record) {
					if (Ext.isObject(record[key]) && record[key].value !== undefined) {
						record[key] = record[key].value;
					}
				}
			}
		}
	};
	acms.Fun.simplify = simplify;
	
	acms.ImageSelector = {
		field  : null,
		window : null,
		clone : function () {
			return {
				field  : null,
				window : null,
				showWindow : this.showWindow
			};
		},
		init : function (comp) {
			var toolbar,
			    is = {
				window : null,
				field : comp,
				showWindow : acms.ImageSelector.showWindow
			};
			
			is.field.on('afterrender', function() {
				toolbar = this.field.getToolbar();
				toolbar.add({
					handler : function () {
						this.showWindow();
					},
					scope : this, 
					text  : acms.ls('IMAGES')
				});
			}, is);
		},
		showWindow : function(handler, scope) {
			var buttons = [],
			    store = Ext.create('Ext.data.Store', {
				fields : ['Id', 'StorageName', 'Identifier', 'Width', 'Height'],
				proxy: {
					type: 'ajax',
					url: acms.mkUrl(encodeURI('/jsonlist?entity=\\entities\\File&type=image&layout=json')),
					reader: {
						type: 'json',
						root: 'items',
						totalProperty : 'count'
					}
				}
			}),
			    imageChooserId = Ext.id();
			
			if (this.window === null) {
				(function () {
					var actions = {
						close :	function() {
							this.window.hide();
						},
						insert : function() {
							var chooser = Ext.ComponentMgr.get(imageChooserId),
							    records = chooser.getSelectionModel().selected;
						
							if (this.field !== null) {
							
								records.each(function(record) {
									var widthId = Ext.id(),
									    heightId = Ext.id(),
									    altId = Ext.id(),
									    alignId = Ext.id(),
									    marginsId = Ext.id(),
									    w = Ext.create('Ext.window.Window', {
									    width : 300,
									    bodyPadding: 10,
										layout : 'anchor',
										items : [{
											xtype : 'atextfield',
											readonly : true,
											value : record.data.Identifier,
											fieldLabel : acms.ls('IMAGE_IDENTIFIER')
										}, {
											xtype : 'anumber',
											value : record.data.Width,
											fieldLabel : acms.ls('IMAGE_WIDTH'),
											id : widthId
										}, {
											xtype : 'anumber',
											value : record.data.Height,
											fieldLabel : acms.ls('IMAGE_HEIGHT'),
											id : heightId
										},{
											xtype : 'atextfield',
											value : record.data.Identifier,
											fieldLabel : acms.ls('IMAGE_ALT'),
											id : altId
										},{
											xtype : 'acmscombo',
											value : 'none',
											data : [['none', acms.ls('ALIGN_NONE')], ['left', acms.ls('ALIGN_LEFT')],['right', acms.ls('ALIGN_RIGHT')]],
											fieldLabel : acms.ls('IMAGE_ALIGN'),
											id : alignId
										},{
											xtype : 'atextfield',
											value : '0px',
											fieldLabel : acms.ls('IMAGE_MARGINS'),
											id : marginsId
										}],
										buttons : [{
											text : acms.ls('INSERT'),
											handler : function() {
												var width  = Ext.ComponentMgr.get(widthId).getValue(),
												    height = Ext.ComponentMgr.get(heightId).getValue(),
												    alt = Ext.ComponentMgr.get(altId).getValue(),
												    align = Ext.ComponentMgr.get(alignId).getValue(),
												    margins = Ext.ComponentMgr.get(marginsId).getValue();
												this.insertAtCursor('<img src="' + acms.path +
													'/image/' + record.data.Identifier +
													'" alt="' + alt + '" width="' + width + '" height="' +
													height + '" style="float: ' + align + '; margin: ' + margins + ';" />');
												w.destroy();
											},
											scope : this
										}]
									});
									w.show();
								}, this.field); // records.each
							} else { // if this.field
								if (handler) {
									handler.call(scope, chooser);
								}
							}
						}
					};
					
					if (this.field !== null) {
						buttons.push({
							text : acms.ls('INSERT'),
							handler : actions.insert,
							scope : this
						},{
							text : acms.ls('INSERT_AND_CLOSE'),
							handler : function() {
								actions.insert.call(this);
								actions.close.call(this);
							},
							scope : this
						});
					} else {
						buttons.push({
							text : acms.ls('SELECT'),
							handler : function() {
								actions.insert.call(this);
								actions.close.call(this);
							},
							scope : this
						});
					}
					buttons.push({
						text : acms.ls('CLOSE'),
						handler : actions.close,
						scope : this
					});
				}).call(this);
				this.window = Ext.create('Ext.window.Window', {
					width : 400,
					modal : true,
					items : [{
						id    : imageChooserId,
						xtype : 'dataview',
						cls   : 'acms-image-selector',
						title : acms.ls('IMAGE_CHOOSER'),
						store : store,
						autoScroll : true,
						tpl   : [
							'<tpl for=".">',
							'<div class="thumb-wrap" id="x-img-{Id}">',
							'<div class="thumb"><img src="' + acms.path + '/image/{Identifier}?box=80" title="{Identifier}"></div>',
							'<span class="x-editable">{Identifier}</span></div>',
							'</tpl>',
							'<div class="x-clear"></div>'
						],
						multiSelect: true,
			            height: 310,
			            trackOver: true,
			            overItemCls: 'x-item-over',
			            itemSelector: 'div.thumb-wrap'
					}],
					buttons : buttons,
					dockedItems : [{
						xtype : 'pagingtoolbar',
						store : store,
						dock  : 'top',
						displayInfo : true
					}]
				});
			}
			store.load();
			this.window.show();
		}
	};

	Ext.define('acms.button.Position', {
		extend : 'Ext.Component',
		alias  : 'widget.position',
		renderTpl : '<table width="39" border="0" cellspacing="0" cellpadding="0" class="dPad">' +
						'<tbody>' +
							'<tr>' +
								'<td> </td>' +
								'<td>' +
									'<span class="d-up"></span>' +
								'</td>' +
								'<td> </td>' +
							'</tr>' +
							'<tr>' +
								'<td>' +
									'<span class="d-left"></span>' +
								'</td>' +
								'<td>' +
									'<span class="d-center"></span>' +
								'</td>' +
								'<td>' +
									'<span class="d-right"></span>' +
								'</td>' +
							'</tr>' +
							'<tr>' +
								'<td> </td>' +
								'<td>' +
									'<span class="d-down"></span>' +
								'</td>' +
								'<td> </td>' +
							'</tr>' +
						'</tbody>' +
					'</table>',
		renderSelectors : {
			btnUp    : 'span.d-up',
			btnDown  : 'span.d-down',
			btnLeft  : 'span.d-left',
			btnRight : 'span.d-right'
		},
		initComponent : function() {
			this.addEvents({
				click : true
			});
			this.callParent(arguments);
		},
		afterRender : function() {
			var directions = ['Up', 'Down', 'Left', 'Right'],
			    i, l, d,
			    cfun = function(direction) {
				return function() {
					this.fireEvent('click', this, direction);
				};
			};
			
			l = directions.length;
			
			for  (i = 0; i < l; i = i + 1) {
				d = directions[i];
				this['btn' + d].on('click', cfun(d), this);
			}
			
			this.callParent(arguments);
		}
	});
	
	Ext.define('acms.field.Form', {
		extend : 'Ext.form.Panel',
		alias  : 'widget.acmsform',
		stateStack : [],
		pushState : function() {
			var state = { };
			this.items.each(function(item) {
				state[item.getId()] = item.disabled;
			});
			this.stateStack.push(state); 
		},
		popState : function() {
			var state = this.stateStack.pop();
			this.items.each(function(item) {
				item.setDisabled(state[item.getId()]);
			});
		},
		setAllDisabled : function (disabled) {
			if (disabled === undefined) {
				disabled = true;
			}
			this.items.each(function(item) {
				item.setDisabled(disabled);
			});
		}
	});
	
	Ext.define('acms.CountButton', {
		extend : 'Ext.button.Button',
		alias  : 'widget.acountbutton',
		count  : '..',
		constructor : function (cfg) {
			if (cfg.text !== undefined) {
				this.baseText = cfg.text;
				cfg.text += ' (' + (cfg.count || this.count) + ')';
			}
			this.callParent(arguments);
		},
		updateText : function () {
			this.superclass.setText.call(this, Ext.String.format('{0} ({1})', this.baseText, this.count));
		},
		getText : function () {
			return this.baseText;
		},
		setText : function (text) {
			this.baseText = text;
			this.updateText();
		},
		getCount : function () {
			return this.count;
		},
		setCount : function (count) {
			this.count = count;
			this.updateText();
		}
	});
	
	Ext.define('acms.field.TextField', {
		extend      : 'Ext.form.field.Text',
		alias       : 'widget.atextfield',
		constructor : function(cfg) {
			if (Ext.isObject(cfg.regex) && cfg.regex.pattern !== undefined) {
				cfg.regex = new RegExp(cfg.regex.pattern, cfg.regex.modifiers);
			}
			this.callParent(arguments);
		},
		filterKeys : function(e) {
			if (Ext.isOpera) {
				return;
			}
			return this.callParent(arguments);
		}
	});
	
	Ext.define('acms.field.NumField', {
		extend : 'Ext.form.field.Number',
		alias  : 'widget.anumber',
		filterKeys : function (e) {
			if (Ext.isOpera) {
				return;
			}
			return this.callParent(arguments);
		}
	});
	
	Ext.define('acms.field.Radio', {
		extend : 'Ext.Component',
		alias  : 'widget.aradio',
		autoEl : {
			tag : 'span',
			cls : 'radio1'
		},
		constructor : function(cfg) {
			if (cfg.id === undefined) {
				cfg.id = Ext.id();
			}
			this.fieldName = cfg.name || cfg.id;
			this.callParant(arguments);
		},
		onRender : function() {
			var el;

			this.callParent(arguments);
			el = this.getEl();
			
			this.fieldId = Ext.id();
			this.field = el.insertSibling({
				tag  : 'input',
				id   : this.fieldId,
				name : this.fieldName
			}, 'after');
			el.on('click', function() {
				
			}, this);
		}
	});
	
	Ext.define('acms.field.TextArea', {
		extend : 'Ext.form.field.TextArea',
		alias  : 'widget.atextarea',
		grow   : true
	});
	
	Ext.define('acms.field.HtmlEditor', {
		extend : 'Ext.form.field.HtmlEditor',
		alias  : 'widget.ahtmleditor',
		plugins : acms.ImageSelector
	});
	
	Ext.define('acms.field.EmailField', {
		extend : 'acms.field.TextField',
		alias  : 'widget.mailfield',
		vtype  : 'email'
	});
	
	Ext.define('acms.field.ComboBox', {
		extend       : 'Ext.form.field.ComboBox',
		alias        : 'widget.acmscombo',
		queryMode    : 'local',
		displayField : 'display',
		valueField   : 'value',
		editable     : false,
		constructor  : function (cfg) {
			var store,
			    data;

			if (cfg.data !== undefined || this.data !== undefined) {
				data = [];
				Ext.Array.each(cfg.data || this.data, function(item) {
					data.push({
						'value'   : item[0],
						'display' : item[1]
					});
				});
				store = Ext.create('Ext.data.Store', {
					fields : ['value', 'display'],
					data   : data
				});
				cfg.store = store;
			} else if (cfg.store === undefined){
				throw acms.createException("No store given for control: " + this.name);
			}
			this.callParent(arguments);
			if (cfg.value) {
				this.setValue(cfg.value);
			}
		}
	});

	Ext.define('acms.field.TimeField', {
		extend : 'Ext.form.field.Time',
		alias  : 'widget.atimefield',
		format : 'H:i:s',
		setValue : function(val) {
			var dval, vals;
			if (Ext.isString(val)) {
				vals = val.split(':');
				dval = new Date(0,0,0,parseInt(vals[0],10),parseInt(vals[1],10),vals[2] === undefined ? 0 : parseInt(vals[2],10));
			} else {
				dval = val;
			}
			this.callParent([dval]);
		},
		getValue : function() {
			var dval = this.callParent(),
			    key,
			    data;
			
			if (dval === null) {
				dval = new Date();
			} else if (Ext.isString(dval)) {
				dval = new Date(dval);
			}
			
			data = {
				h : dval.getHours(),
				m : dval.getMinutes(),
				s : dval.getSeconds()
			};
			
			for (key in data) {
				if (data[key] < 10) {
					data[key] = '0' + data[key];
				}
			}
			
			return dval === null ? '00:00:00' : Ext.String.format('{0}:{1}:{2}', data.h, data.m, data.s);
		}
	});
	
	Ext.define('acms.field.DateField', {
		extend : 'Ext.form.field.Date',
		alias  : 'widget.adatefield',
		format : 'Y-m-d',
		setValue : function(val) {
			var dval, vals;
			if (Ext.isString(val)) {
				vals = val.split('-');
				dval = new Date(parseInt(vals[0],10),parseInt(vals[1],10)-1,parseInt(vals[2],10));
				if(isNaN(dval)) {
					dval = new Date();
				}
			} else if (val === undefined) {
				dval = new Date();
			} else {
				dval = val;
			}
			this.callParent([dval]);
		},
		getValue : function() {
			var dval = this.callParent(),
			    m, s,
			    d;
			
			if (dval === null || !Ext.isDate(dval)) {
				dval = new Date();
			}
			m = dval.getMonth() + 1;
			if (m < 10) {
				m = '0' + m;
			}
			d = dval.getDate();
			if (d < 10) {
				d = '0' + d;
			}
			s = Ext.String.format('{0}-{1}-{2}', dval.getFullYear(), m, d);
			return s;
		}
	});
	
	Ext.define('acms.field.DateTimeField', {
		extend : 'Ext.form.FieldContainer',
		alias  : 'widget.datetimefield',
		layout : 'hbox',
		constructor : function(cfg) {
			cfg.items = [ ];
			
			if (cfg.id !== undefined) {
				cfg.items.push({
					xtype  : 'adatefield',
					id     : cfg.id + '_Date',
					submitValue : false
				});
				cfg.items.push({
					xtype  : 'atimefield',
					id     : cfg.id + '_Time',
					submitValue : false
				});
				cfg.items.push({
					xtype : 'hidden',
					id    : cfg.id,
					name  : cfg.name
				});
				cfg.id = cfg.id + '_Container';
				cfg.name = undefined;
			}
			this.callParent(arguments);
			this.dateControl  = this.items.get(0);
			this.timeControl  = this.items.get(1);
			this.valueControl = this.items.get(2);
			if (cfg.value) {
				this.setValue(cfg.value);
			}
			this.updateValueControl();
			this.dateControl.on('change', this.updateValueControl, this);
			this.timeControl.on('change', this.updateValueControl, this);
		},
		updateValueControl : function() {
			var val = this.getValue();
			this.valueControl.setRawValue(val);
		},
		setValue : function(value) {
			var vals = value.split(/[ \t]+/);
			this.dateControl.setValue(vals[0]);
			this.timeControl.setValue(vals[1] === undefined ? '00:00:00' : vals[1]);
		},
		getValue : function() {
			return Ext.String.format('{0} {1}', this.dateControl.getValue(), this.timeControl.getValue());
		}
	});
	
	Ext.define('acms.field.BoolField', {
		extend       : 'acms.field.ComboBox',
		alias        : 'widget.boolfield',
		data         : [
			['True',  acms.ls('TRUE')],
			['False', acms.ls('FALSE')]
		],
		queryMode    : 'local',
		displayField : 'display',
		valueField   : 'value',
		editable     : false,
		constructor  : function (cfg) {
			if (cfg.value !== undefined) {
				if (cfg.value === true) {
					cfg.value = 'True';
				} else if (cfg.value === false) {
					cfg.value = 'False';
				}
			}
			this.callParent(arguments);
		}
	});

	Ext.define('acms.field.WhichField', {
		extend        : 'acms.field.ComboBox',
		alias         : 'widget.whichfield',
		queryMode     : 'local',
		displayField  : 'display',
		valueField    : 'value',
		editable      : false,
		manualSelect  : false,
		initComponent : function() {
			this.on('select', function() {
				this.manualSelect = true;
			}, this);
			this.callParent(arguments);
		},
		xfields : {
			wired : null,
			mobile : null
		},
		addXField : function (comp, which) {
			this.xfields[which] = comp;
			comp.on('change', this.restate, this);
			this.restate();
		},
		restate : function() {
			var val, dis = true;
			if (this.xfields.mobile === null || this.xfields.mobile.getValue() === '') {
				val = 'Wired';
			} else {
				if (this.xfields.wired !== null && this.xfields.wired.getValue() !== '') {
					dis = false;
				}
				val = 'Mobile';
			}
			if (false === this.manualSelect || dis === true) {
				this.setValue(val);
				this.manualSelect = true;
			}
			this.setDisabled(dis);
		},
		constructor : function(cfg) {
			cfg.disabled = true;
			this.callParent(arguments);
		}
	});
	
	Ext.define('acms.field.UrlField', {
		extend : 'Ext.form.field.Text',
		alias  : 'widget.urlfield',
		vtype  : 'url',
		initComponent : function() {
			this.on('focus', function() {
				if (this.getRawValue().length === 0) {
					this.setRawValue('http://');
				}
			}, this);
			this.callParent(arguments);
		}
	});
	
	Ext.define('acms.field.RemoteComboBoxReader', {
		extend : 'Ext.data.reader.Json',
		alias  : 'widget.acmsremotecomboreader',
		root   : 'items',
		totalProperty : 'count',
		readRecords : function () {
			var resultSet;
			
			resultSet = this.callParent(arguments);
			simplify(resultSet.records);
			return resultSet;
		}
	});
	
	Ext.define('acms.field.RemoteComboBox', {
		extend       : 'Ext.form.field.ComboBox',
		alias        : 'widget.acmsremotecombo',
		queryMode    : 'remote',
		listBase     : 'jsonlist',
		allowBlank   : true,
		displayField : 'Address',
		valueField   : 'Id',
		editable     : false,
		pageSize     : 25,
		baseUri      : null,
		condition    : null,
		generateUrl  : function () {
			return this.baseUri + (this.condition ? ('&condition=' + Ext.encode(this.condition)) : '');
		},
		regenerateUrl : function () {
			this.store.getProxy().url = this.generateUrl();
		},
		constructor  : function (cfg) {
			var store,
			    reader,
			    value,
			    listBase = cfg.listBase || this.listBase,
			    uri,
			    condition,
			    entity = cfg.entity || this.entity,
			    fields = cfg.fields || this.fields;
			
			reader = Ext.create('acms.field.RemoteComboBoxReader', { });

			value = cfg.value;
			
			if (entity !== undefined && fields !== false) {
				this.baseUri = acms.mkUrl('/' + listBase + '?entity=' + entity + '&layout=json');
				this.condition = this.condition || cfg.condition;
				store = Ext.create('Ext.data.Store', {
					fields     : fields,
					remoteSort : true,
					autoload   : false,
					proxy  : {
						type   : 'ajax',
						url    : encodeURI(this.generateUrl()),
						reader : reader,
						extraParams : cfg.extraParams || this.extraParams
					}
				});
				cfg.store = store;
			}
			this.callParent(arguments);
			if (Ext.isObject(value)) {
				this.store.loadData([value]);
				simplify(this.store.data.items);
				this.setValue(value.Id);
			}
		}
	});
	
	Ext.define('acms.ui.RemoteComboBox', {
		extend : 'acms.field.RemoteComboBox',
		alias  : 'widget.uicombo',
		width  : 180,
		baseBodyCls  : 'select180',
		listeners : {
			afterrender : function (comp) {
				var input = comp.getEl().down('input');
				input.applyStyles({
					width : '151px'
				});
			},
			select : function (comp) {
				var input = comp.getEl().down('input');
				input.applyStyles({
					width : '151px'
				});
			},
			blur : function (comp) {
				var input = comp.getEl().down('input');
				input.applyStyles({
					width : '151px'
				});
			}
		},
		validate : function () {
			var valid = this.callParent(arguments);
			if (!valid) {
				this.getEl().addCls('invalid');
			} else {
				this.getEl().removeCls('invalid');
			}
			return valid;
		}
	});
	
	Ext.define('acms.field.RemoteAddComboBox', {
		extend : 'acms.field.RemoteComboBox',
		alias  : 'widget.acmsremotecomboadd',
		onRender : function() {
			var el, input, div, ct;
			this.callParent(arguments);
			el = this.getEl();
			input = el.down('input');
			div = el.down('div.x-form-item-body');
			ct = el.insertFirst({
				tag : 'div'
			});
			ct.applyStyles({
				float : 'right'
			});
			Ext.create('Ext.Button', {
				renderTo : ct,
				icon     : acms.path + '/static/imgs/actions/add22.png',
				handler  : this.addHandler,
				scope    : this.addScope,
				width    : 30,
				height   : 22
			});
			this.on('resize', function() {
				input.applyStyles({
					width : input.getWidth() - 32 + 'px'
				});
				div.applyStyles({
					width : div.getWidth() - 32 + 'px'
				});
			});
		}
	});
	
	Ext.define('acms.field.ImageUploader', {
		extend : 'Ext.container.Container',
		alias  : 'widget.aimageuploader',
		layout : 'vbox',
		onLoadSet : false,
		components : { },
		getImgComponent : function () {
			if (this.components.img === undefined) {
				this.components.img = Ext.ComponentMgr.get(this.img_id);
			}
			return this.components.img;
		},
		getFileComponent : function () {
			if (this.components.file === undefined) {
				this.components.file = Ext.ComponentMgr.get(this.file_id);
			}
			return this.components.file;
		},
		getDirectImg : function () {
			if (this.components.dimg === undefined) {
				this.components.dimg = Ext.getBody().createChild({
					tag : 'img'
				});
			}
			return this.components.dimg;
		},
		constructor : function (cfg) {
			var id, name;
			
			cfg.id   = cfg.id || Ext.id();
			cfg.name = cfg.name || Ext.id();
			name   = 'ImageUploader_' + cfg.name;
			this.img_id  = 'ImageUploader_' + cfg.id + '_img';
			this.file_id = 'ImageUploader_' + cfg.id;
			
			cfg.items = [{
				xtype  : 'container',
				layout : {
					type  : 'vbox',
					align : 'center'
				},
				items : [{
					xtype  : 'image',
					id     : this.img_id,
					height : 300
				}]
			},{
				xtype : 'filefield',
				name  : cfg.name,
				id    : this.file_id,
				listeners : {
					change : function() {
						var img = this.getDirectImg(),
						    file = this.getFileComponent();

						if (this.onLoadSet === false) {
							img.on('load', function() {
								var imgc;
								this.size = {
									width  : img.getWidth(),
									height : img.getHeight()
								};
								imgc = this.getImgComponent();
								imgc.setSrc(img.dom.src);
							}, this);
							this.onLoadSet = true;
						}
						img.dom.src = file.getValue();
					},
					scope : this
				}
			}];
			
			cfg.id   = id;
			cfg.name = name;
			cfg.height = 330;
			this.callParent(arguments);
		}
	});
	
	Ext.define('acms.field.ImagePicker', {
		extend : 'Ext.form.field.Trigger',
		alias  : 'widget.imagepicker',
		hiddenValue : null,
		editable : false,
		constructor : function(cfg) {
			this.imageSelector = acms.ImageSelector.clone();
			this.callParent(arguments);
		},
		listeners : {
			afterrender : function (comp) {
				Ext.get(comp.getInputId()).on('click', function() {
					comp.onTriggerClick();
				});
			}
		},
		getSubmitValue : function() {
			return this.hiddenValue;
		},
		rawToValue : function(raw) {
			return this.hiddenValue;
		},
		valueToRaw : function (raw) {
			this.hiddenValue = Ext.isObject(raw) ? raw.Id : null;
			return Ext.isObject(raw) ? raw.Identifier : null;
		},
		onTriggerClick : function() {
			this.imageSelector.showWindow(function(chooser) {
				var record = chooser.getSelectionModel().selected.first();
				this.setValue({
					Id : record.data.Id,
					Identifier : record.data.Identifier
				});
			}, this);
		}
	});
	
	Ext.define('acms.FilterWindow', {
		extend : 'Ext.window.Window',
		alias  : 'widget.acmsfilterwindow',
		constructor : function (cfg) {
			var data = cfg.filterData,
			    items = [ ],
			    self = this;
			
			this.ids = [];
			
			Ext.Array.each(data, function (item) {
				var id = 'filter-' + item.id,
				    valueField;
				
				switch (item.type) {
					case 'enum':
						valueField = {
							xtype : 'acmscombo',
							data : item.options
						};
						break;
					case 'datetime':
						valueField = {
							xtype : 'datetimefield'
						};
						break;
					case 'number':
						valueField = {
							xtype : 'anumber'
						};
						break;
					case 'string':
						valueField = {
							xtype : 'atextfield'
						};
						break;
				}
				valueField.id = id + '-value';
				valueField.width = 300;
				if (item.value !== undefined) {
					valueField.value = item.value;
				}
				if (item.funValue === undefined) {
					valueField.disabled = true;
				}
				
				self.ids.push(item.id);
				
				this.push({
					xtype  : 'container',
					layout : 'hbox',
					width  : 600,
					items  : [{
						xtype : 'label',
						id    : id + '-label',
						forId : id + '-filter',
						text  : item.text,
						width : 100
					}, {
						xtype : 'atextfield',
						id : id,
						readOnly : true,
						value : item.fieldId,
						width : 100
					}, {
						xtype : 'acmscombo',
						id : id + '-filter',
						data : item.funs,
						value : item.funValue === undefined ? -1 : item.funValue,
						width : 100,
						filterDataItem : item,
						listeners : {
							select : function (self) {
								Ext.ComponentMgr.get(valueField.id).setDisabled(self.getValue() == -1);
							}
						}
					}, valueField]
				});
			}, items);
			
			cfg.items = items;
			cfg.buttons = [{
				text : acms.ls('CANCEL'),
				handler : function () {
					this.destroy();
				},
				scope : this
			}, {
				text : acms.ls('APPLY'),
				handler : function() {
					this.applyFilters();
					this.fbutton.applyCondition();
					this.destroy();
				},
				scope : this
			}];
			this.callParent(arguments);
		},
		applyFilters : function() {
			Ext.Array.each(this.ids, function(id) {
				var filter = Ext.ComponentMgr.get('filter-' + id + '-filter'),
				    value;
				if (filter.getValue() != -1) {
					value = Ext.ComponentMgr.get('filter-' + id + '-value');
					filter.filterDataItem.value = value.getValue();
					filter.filterDataItem.funValue = filter.getValue();
				} else {
					if (filter.filterDataItem.value !== undefined) {
						delete filter.filterDataItem.value;
					}
					if (filter.filterDataItem.funValue != undefined) {
						delete filter.filterDataItem.funValue;
					}
				}
			}, this);
			return this.fbutton.getCondition();
		}
	});
	
	Ext.define('acms.Filter', {
		extend : 'Ext.button.Button',
		alias  : 'widget.acmsfilter',
		anyStr : null,
		constructor : function (cfg) {
			cfg.text = acms.ls('FILTER');
			this.callParent(arguments);
		},
		handler : function (self) {
			var w = Ext.create('acms.FilterWindow', {
				filterData : self.filterData,
				bodyPadding : 10,
				list : this.list,
				fbutton : this
			});
			w.show();
		},
		cc : acms.Fun.createCondition,
		jc : acms.Fun.joinCondition,
		r2s : {
			0 : acms.ls('EQUALS'),
			1 : acms.ls('GREATER_THAN'),
			2 : acms.ls('LOWER_THAN'),
			3 : acms.ls('LIKE'),
			4 : acms.ls('GREATER_OR_EQUALS'),
			5 : acms.ls('LOWER_OR_EQUALS'),
			6 : acms.ls('NOT_EQUALS')
		},
		rx2s : {
			0 : acms.ls('STR_AND'),
			1 : acms.ls('STR_OR')
		},
		getAnyCondition : function() {
			return this.anyStr === null ? null : this.cc('@any', this.anyStr, 3); // 3 === LIKE
		},
		getCondition : function() {
			var c = null;
			Ext.Array.each(this.filterData, function(filterDataItem) {
				if (filterDataItem.value !== undefined && filterDataItem.funValue !== undefined) {
					c = this.jc(c, this.cc(filterDataItem.fieldId, filterDataItem.value, filterDataItem.funValue), 0);
				}
			}, this);
			return this.jc(this.getAnyCondition(), c, 0);
		},
		getConditionAsString : function(c) {
			var filters = c || this.getCondition(),
			    self = this,
			    c2s = function(c) {
				var result,
				    a = ''+c.ClassName; // WTF?
				if (a == '.data.SimpleCondition') {
					result = c.Field + ' ' + self.r2s[c.Pattern.Relation] + ' ' + c.Pattern.Value; 
				} else {
					result = '(' + c2s(c.Condition1) + ') ' + self.rx2s[c.Relation] + ' (' + c2s(c.Condition2) + ')'; 
				}
				return result;
			}
			return filters !== null ? c2s(c) : acms.ls('NONE');
		},
		applyCondition : function() {
			var c = this.getCondition();
			if (c === null) {
				delete this.list.getStore().getProxy().extraParams.condition;
			} else {
				this.list.getStore().getProxy().extraParams.condition = Ext.encode(c);
			}
			this.setText(acms.ls('FILTER') + ': ' + this.getConditionAsString(c));
			this.list.getStore().load();
		},
		mergeFilterData : function(data) {
			Ext.Array.each(this.filterData, function (fdata) {
				if (data[fdata.id] !== undefined) {
					acms.Object.mergeTo(fdata, data[fdata.id]);
				}
			});
			this.applyCondition();
		},
		setAnyStr : function (str) {
			this.anyStr = str;
			this.applyCondition();
		},
		clearAnyStr : function () {
			this.anyStr = null;
			this.applyCondition();
		}
	});
	
	Ext.define('SearchText', {
		extend : 'acms.field.TextField',
		alias  : 'widget.searchtext',
		emptyText : acms.ls('SEARCH_ANY'),
		enableKeyEvents : true,
		listeners : {
			blur : function(comp) {
				if (comp.bfilter !== undefined) {
					if (comp.getValue() !== null && comp.getValue().length > 0) {
						comp.bfilter.setAnyStr(comp.getValue());
					} else {
						comp.bfilter.clearAnyStr();
					}
				}
			},
			keyup : function(comp, e) {
				if (e.keyCode === 13) {
					comp.fireEvent('blur', comp);
				}
			}
		}
	});
	
	Ext.define('acms.FormBuilder', {
		extend : 'Ext.util.Observable',
		constructor : function() {
			this.addEvents(acms.C.Initialized);
			this.callParent(arguments);
		},
		build : function(cfg) {
			var menuItems, form;
			
			cfg.autoScroll = true;
			cfg.additionalArgs = cfg.additionalArgs || { };
			cfg.buttons = [
				{
					text    : cfg.strings.reset,
					handler : function() {
						this.up('form').getForm().reset();
					}
				},{
					text     : cfg.strings[cfg.action === 'edit' ? 'save' : 'create'],
					formBind : true,
					handler  : function() {
						var form,
						    panel;
						
						panel = this.up('form');
						form = panel.getForm();
						panel.pushState();
						panel.setAllDisabled(false);
						form.submit({
							url    : acms.path + '/index.php',
							method : 'POST',
							params : Ext.Object.merge({
								page     : 'jsonentity',
								action   : cfg.action === 'edit' ? 'save' : 'create',
								language : acms.locale,
								entity   : cfg.entity,
								layout   : 'json'
							}, cfg.additionalArgs),
							success : function(form, action) {
								var data;
								panel.popState();
								Ext.Msg.show({
									title   : 'Success', //TODO: localize
									msg     : 'Saved successfully!',
									buttons : Ext.Msg.OK,
									icon    : Ext.Msg.INFO
								});
								if (action.response && action.response.responseText) {
									data = Ext.decode(action.response.responseText);
									if (data && data.location) {
										window.location.href = data.location;
									}
								}
							},
							failure : function(form, action) {
								var str,
								    data;
								
								panel.popState();
								switch (action.failureType) {
									case Ext.form.action.Action.CLIENT_INVALID:
										str = 'Invalid client validation!';
										break;
									case Ext.form.action.Action.CONNECT_FAILURE:
										if (action.response && action.response.responseText) {
											data = Ext.decode(action.response.responseText);
										}
										str = data.message;
										break;
									case Ext.form.action.Action.LOAD_FAILURE:
										str = 'Invalid response!';
										break;
									case Ext.form.action.Action.SERVER_INVALID:
										if (action.response && action.response.responseText) {
											data = Ext.decode(action.response.responseText);
										}
										str = data.message;
										break;
								}
								Ext.Msg.show({
									title   : 'Error', //TODO: localize
									msg     : str,
									buttons : Ext.Msg.OK,
									icon    : Ext.Msg.ERROR
								});
							}
						});
					}
				}
			];
			if (cfg.multilang === true) {
				cfg.buttons.unshift({
					text     : cfg.strings.editlang,
					disabled : cfg.action !== 'edit',
					handler  : function() {
						window.location = acms.mkUrl(encodeURI('/adminlanglist?' + 
							'entity=' + cfg.langEntity + '&' +
							'foreign=' + cfg.shortName + '&' +
							'foreignval=' + cfg.foreignval));
					}
				});
			}
			if (Ext.isArray(cfg.assignable) && cfg.assignable.length > 0) {
				menuItems = [ ];
				Ext.Array.each(cfg.assignable, function(item) {
					var i = {
						text : item.text
					};
					if (item.url !== undefined) {
						i.listeners = {
								click : function() {
									window.location.href = this;
								},
								scope : item.url
						};
					}
					this.push(i);
				}, menuItems);
				cfg.buttons.unshift({
					text : cfg.strings.assignments,
					menu : menuItems
				});
			}
			if (Ext.isArray(cfg.additionalButtons)) {
				Ext.Array.each(cfg.additionalButtons, function(button) {
					this.unshift({
						text    : button.text,
						handler : function() {
							window.open(button.url, '_blank');
						}
					});
				}, cfg.buttons);
			}
			form = Ext.create('acms.field.Form', cfg);
			this.fireEvent(acms.C.Initialized, form.getId(), form);
		}
	});
	
	acms.Form = Ext.create('acms.FormBuilder');
	acms.events.fireEvent(acms.events.FORM_INITIALIZED);
});


