package classes.matuto.ui{
	

	
	import classes.matuto.events.FormEvent;
	import classes.matuto.model.Model;
	import classes.matuto.utils.form.TabIndex;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.FocusEvent;
	import flash.text.TextField;

	public class Form{
		
		public static const NUMBER 		:String = "number";
		public static const MAIL		:String = "mail";
		public static const STRING		:String = "string";
		public static const CPF			:String = "cpf";
		public static const TEL			:String	= "tel";
		public static const DATA		:String = "data";
		public static const ALL			:String = "all";
		
		public var fields_arr 			:Array;
		public var params_arr			:Array;
		
		private var command				:String;
		private var dispatcher 			:EventDispatcher = new EventDispatcher();
		
		public var podeApagar			:Boolean = false;
		
		private var sucessoMensa		:String;
		private var duranteMensa		:String;
		
			public		var message	:String = "";

		public function Form( command :String, sucesso:String = "Enviada com sucesso",durante:String="Enviando" )
		{
			
			this.command 	= command;
			
			fields_arr 		= new Array();
			params_arr 		= new Array();
			
			sucessoMensa	= sucesso;
			duranteMensa	= durante;
		}
		
		
		/**
		 *
		 * @param	field Campo de texto
		 * @param	type Tipos de caracteres que deverá conter o campo de texto. Podem ser acessados diretamente pela classe, ex: Form.NUMBER .
		 * @param	fotmat Formatação do caracteres do campo, ex: "**-*****,**". O '*' representa os caracteres, e os demais serão fixos.
		 * @param	limit Limite máximo de caracteres
		 * @param	call Ao submeter o formulário, a função será chamada. Serve para realizar alguma operação fora da rotina.
		 */
		public function addField( name :String, field :TextField, defaultValue :String = "", type :String = "all", format :String = null, limit :int = 0, password :Boolean = false, call :Function = null, valida:Boolean = true ) :void
		{
			
			field.text = defaultValue;
			
			if ( limit != 0 ) 		field.maxChars = limit;
			if ( type == NUMBER ) 	field.restrict = "0123456789";
			if ( type == CPF ) 		{
				field.restrict = "0123456789";
				field.maxChars = 11;
			}
			if ( password ) field.displayAsPassword = password;
			if ( type == STRING )	field.addEventListener( Event.CHANGE, type_string );
			if ( format ) {
				field.maxChars = format.length;
				field.addEventListener( Event.CHANGE, function( event :Event ) :void{ field_format(event.target as TextField, format) } );
			}
			
			fields_arr.push( { name:name, field:field, defaultValue:defaultValue, type:type, call:call, valid:valida } );
			
			//field.tabIndex = fields.length;
			TabIndex.registerTabIndex( field );
			
			field.addEventListener( FocusEvent.FOCUS_IN, focus_in );
			field.addEventListener( FocusEvent.FOCUS_OUT, focus_out );
			
	
		}
		
		
		public function addParam( id :String, value :* ) :void
		{
			
			params_arr.push( { id:id, value:value } );
			
		}
		
		
		private function focus_in( event :FocusEvent ) :void
		{
			
			var str :String = event.target.text;
			
			for (var i:int = 0; i < fields_arr.length; i++ )
			{
				
				var atual :Object = fields_arr[i];
				
				var field			:TextField 	= atual.field;
				var defaultValue 	:String 	= atual.defaultValue;
				
				if ( field == event.target ) {
					
					if ( str == defaultValue ) field.text = "";
					
					break;
					
				}
				
			}
			
		}
		
		
		private function focus_out( event :FocusEvent ) :void
		{
			
			var str :String = event.target.text;
			
			for (var i:int = 0; i < fields_arr.length; i++ )
			{
				
				var atual :Object = fields_arr[i];
				
				var field			:TextField 	= atual.field;
				var defaultValue 	:String 	= atual.defaultValue;
				
				if ( field == event.target ) {
					
					if ( str == "" || str == " " ) field.text = defaultValue;
					
					break;
					
				}
				
			}
			
		}
		
		
		private function type_string( event :Event ) :void
		{
			
			var str :String = event.target.text;
			
			var char :* = escape( str.charAt( str.length - 1 ) );
			
			if ( !isNaN( char ) ) event.target.text = str.substr( 0, str.length - 1 );
			
		}
		
		
		private function field_format( field :TextField, format :String ) :void
		{
			
			var str :String = field.text;
			
			if ( format.charAt(str.length - 1) != "*" ) field.text = str.substr( 0, str.length - 1 ) + format.charAt(str.length - 1);
			
		}
		
		
		
		public function validation() :Boolean
		{
			
			var bool 	:Boolean = true;

			for ( var i :int = 0; i < fields_arr.length; i++ )
			{
				
				var obj :Object = fields_arr[i];
				
				var name			:String		= obj.name;
				var field 			:TextField 	= obj.field;
				var defaultValue	:String 	= obj.defaultValue;
				var type 			:String 	= obj.type;
				var call			:Function 	= obj.call;
				
				
				
				
				//trace(field.text.replace(".", "").replace(".", "").replace("-", ""));
				
				if (obj.valid)
				{
					if ( field.text == "" || field.text == " " || field.text == defaultValue ) {
					
						field.stage.focus = field;
						message = "Campo " + name + " esta vazio";
						bool = false;
						break;
						
					}else if ( type == MAIL && !mailValidation(field.text) ) {
						
						field.stage.focus = field;
						message = "Email invalido";
						bool = false;
						break;
						
					}else if ( type == CPF && !cpfValidation(field.text.replace(".", "").replace(".", "").replace("-", ""))) {
						
						field.stage.focus = field;
						message = "CPF invalido";
						bool = false;
						break;
						
					}
				}
				
			}
			
			if (!bool) dispatchEvent( new FormEvent( FormEvent.STATUS, { message:message, sent:false, field:name } ) );
			
			return bool;
			
		}
		
		
		private function mailValidation( text :String ) :Boolean
		{
			
			var pos :int = text.indexOf("@");
			var p	:int = text.indexOf(".", pos );
			
			if ( pos < 1 || ( pos >= 1 && p < (pos+2) ) ) return false;
			
			return true;
			
		}
		
		
		public function cpfValidation( text :String ) :Boolean
		{
			
			var soma1 :Number =0;
			var soma2 :Number = 0;
			
			for ( var i :int = 0; i < 9; i++)
			{
				
				//if ( isNaN( Number(text.charAt(i)) ) ) continue;
				
				var numero1 :Number = Number( text.charAt(i) )*(i+1);
				soma1 += numero1;
			}
			
			for ( i = 1; i < 10; i++ )
			{
				//if ( isNaN( Number(text.charAt(i)) ) ) continue;
				
				var numero2 :Number = Number( text.charAt(i) )*i;
				soma2 += numero2;
				
			}
			
			var v1 :Number = soma1%11;
			var v2 :Number = soma2 % 11;
			
			if(v1==10)v1=0;
			if(v2==10)v2=0;
			
			if (v1 == Number(text.charAt(9)) && v2 == Number(text.charAt(10)) ) return true;
			else return false;
			
			return false;
			
		}
		
		
		
		public function submit() :void
		{
			
			if ( validation() )
			{
				
				var info 	:Object = new Object();
				
				for (var i:int = 0; i < fields_arr.length; i++ )
				{
					
					var obj :Object = fields_arr[i];
					
					var name	:String 	= obj.name;
					var field 	:TextField 	= obj.field;
					
					info[name] = field.text;
					
				}
				
				if ( params_arr.length > 0 )
				{
					
					var params_obj :Object = new Object();
					
					for ( i = 0; i < params_arr.length; i++ )
					{
						
						var param :Object = params_arr[i];
						
						params_obj[ param.id ] = param.value;
						
					}
					
					info.params = params_obj;
					
				}
				
				
				dispatchEvent( new FormEvent( FormEvent.STATUS, { message:duranteMensa, sent:false } ) );
								
				Model.AMF_CONNECT(command,sent_result,"erro no formulario",info);
				
			}
			
			
		}
		
		
		private function sent_result( res :Object ) :void
		{
						
			if( res ) dispatchEvent( new FormEvent( FormEvent.STATUS, { message:sucessoMensa,dado:res,sent:true } ) );
			
			if(!podeApagar)
			clear();
			
		}
		
		
		
		public function clear( params :Object = null ) :void
		{
			
			for (var i:int = 0; i < fields_arr.length; i++ )
			{
				
				var obj :Object = fields_arr[i];
				
				var field 			:TextField 	= obj.field;
				var defaultValue 	:String 	= obj.defaultValue;
				
				field.text = defaultValue;
				
			}
			
		}
		
		
		//##############################################
		// EVENT CONTROLS
		//##############################################
		
		
		public function addEventListener(type :String, listener :Function, useCapture :Boolean = false, priority :int = 0, useWeakReference :Boolean = false) :void
		{
			dispatcher.addEventListener(type, listener, useCapture, priority);
		}
		
		public function dispatchEvent(evt :Event) :Boolean
		{
			return dispatcher.dispatchEvent(evt);
		}
		
		public function hasEventListener(type :String) :Boolean
		{
			return dispatcher.hasEventListener(type);
		}
		
		public function removeEventListener(type :String, listener :Function, useCapture :Boolean = false) :void
		{
			dispatcher.removeEventListener(type, listener, useCapture);
		}
		
		public function willTrigger(type :String) :Boolean
		{
			return dispatcher.willTrigger(type);
		}
		
		
	}
	
}