package {	
	import flash.events.TimerEvent;
	import flash.text.TextField;
	
	public class Movimento {
		// Constantes
		public static const COLOCAR:String = "colocar";
		public static const ATACAR:String = "atacar";
		public static const MOVER:String = "mover";
		public static const FIM_ETAPA:String = "fim etapa";
		public static const NAO_TROCAR:String = "nao trocar";
		
		// Propriedades
		public var tipo:String;
		public var origem:Territorio;
		public var alvo:Territorio;
		public var num:int;
		public var dados:Array;
		public var perdas_alvo:int;
		public var perdas_origem:int;
		public var movidos:int;
		public var eliminado:Jogador;
		public var max:int;
		
		// Contrói o objeto
		public function Movimento(tipo:String):void {
			this.tipo = tipo;
		}
		
		// Executa o movimento, porém sem alterar a interface
		// Retorna true se o jogador ganhou
		public function simular():Boolean {
			var num_d:int, i:int, carta:Carta, j:int;
			var dono_origem:Jogador, dono_alvo:Jogador, cartas:Object;
			if (tipo == COLOCAR) {
				alvo.soldados += num;
			} else if (tipo == ATACAR) {
				// Encontra os donos
				dono_origem = Relacao.get_relacao(origem, Relacao.DONO);
				dono_alvo = Relacao.get_relacao(alvo, Relacao.DONO);
				
				// Calcula o número de dados da defesa
				num_d = Math.min(3, alvo.soldados);
				
				// Sorteia os dados de ataque
				dados = [[], []];
				for (i=0; i<num; i++) {
					dados[0].push(dono_origem.get_dado());
				}
				dados[0].sort(Array.NUMERIC | Array.DESCENDING);
				
				// Sorteia os dados de defesa
				for (i=0; i<num_d; i++) {
					dados[1].push(dono_alvo.get_dado());
				}
				dados[1].sort(Array.NUMERIC | Array.DESCENDING);
				
				// Compara os dados e calcula as perdas
				perdas_origem = 0;
				perdas_alvo = 0;
				for (i=0; i<Math.min(num, num_d); i++) {
					if (dados[0][i]>dados[1][i]) {
						// Ataque ganha
						perdas_alvo++;
						alvo.soldados--;
						dono_alvo.perdas[dono_origem.id-1]++;
					} else {
						// Defesa ganha
						perdas_origem++;
						origem.soldados--;
						dono_origem.perdas[dono_alvo.id-1]++;
					}
				}
				
				// Verifica se o território foi conquistado
				if (alvo.soldados == 0) {
					// Muda o dono
					Relacao.desrelacionar(alvo, dono_alvo, Relacao.DONO);
					Relacao.relacionar(alvo, dono_origem, Relacao.DONO);
					alvo.soldados = 1;
					origem.soldados--;
					movidos = 1;
					
					// Dá a carta
					if (!dono_origem.ganhou_carta && Relacao.get_relacoes(dono_origem, Relacao.CARTA).length<5) {
						dono_origem.ganhou_carta = true;
						j = 0;
						do {
							carta = Grafica.cartas[Math.floor(Math.random()*Grafica.cartas.length)];
							j++;
						} while (Relacao.get_relacoes(carta, Relacao.CARTA).length != 0 && j<1000);
						if (j<1000) {
							Relacao.relacionar(carta, dono_origem, Relacao.CARTA);
							dono_origem.ultima_carta = carta;
						}
					}
					
					// Verifica se o jogador alvo foi eliminado
					if (Relacao.get_relacao(dono_alvo, Relacao.DONO) === null) {
						// Desativa o jogador e passa suas cartas para o atacante
						dono_alvo.ativo = false;
						cartas = Relacao.get_relacoes(dono_alvo, Relacao.CARTA);
						for (i=0; i<cartas.length; i++) {
							Relacao.desrelacionar(cartas[i], dono_alvo, Relacao.CARTA);
							Relacao.relacionar(cartas[i], dono_origem, Relacao.CARTA);
						}
						eliminado = dono_alvo;
					}
					
					// Se for o caso, chama a inteligência para mover quantos soldados ela quiser
					if (!Reguladora.vez.humano) {
						Inteligente.mover_ataque(this);
					}
				}
				
				// Verifica se o jogador ganhou
				if (dono_origem.ganhou(this)) {
					Reguladora.ganhador = dono_origem;
					return true;
				}
			} else if (tipo == MOVER) {
				origem.soldados -= num;
				alvo.soldados += num;
				origem.livres -= num;
			}
			return false;
		}
		
		// Cria o timer para exibir o movimento depois de um tempo
		// Retorna a duração do movimento
		public function executar(atraso:int=0):int {
			Reguladora.timeout(executar2, atraso);
			
			// Calcula a duração
			if (tipo == COLOCAR) {
				return 1000*Reguladora.velocidade;
			} else if (tipo == FIM_ETAPA) {
				return 1000*Reguladora.velocidade;
			} else if (tipo == NAO_TROCAR) {
				return 1000*Reguladora.velocidade;
			} else if (tipo == ATACAR) {
				return (movidos ? 5500 : 4500)*Reguladora.velocidade+(eliminado ? 2500*(Reguladora.velocidade+1) : 0);
			} else if (tipo == MOVER) {
				return 1000*Reguladora.velocidade;
			}
			return 0;
		}
		
		// Mostra o movimento para o usuário, alterando a interface
		private function executar2(evento:TimerEvent):void {
			var i:int, cont:Continente, restantes:int;
			if (tipo == COLOCAR) {
				// Destaca o continente, se preciso
				cont = Relacao.get_relacao(alvo, Relacao.CONTINENTE);
				if (Reguladora.etapa == Reguladora.CONTINENTE && Grafica.continente_destacado !== cont) {
					Grafica.atualizar_territorios();
					Grafica.destacar_continente(cont);
				}
				
				// Atualiza o contador de exércitos restantes
				restantes = int(Grafica.root["txt_restantes"].text);
				if (restantes == 0) {
					Grafica.root["txt_restantes"].text = Reguladora.formatar_num(max, 3);
					restantes = max;
				}
				Grafica.root["txt_restantes"].text = Reguladora.formatar_num(restantes-num, 3);
				
				Grafica.atualizar_territorio(alvo, {"delta" : num, "fundo" : 2, "aviso" : true});
				
				// Som
				if (Reguladora.velocidade>Math.random()) {
					(new SomDireito).play();
				}
			} else if (tipo == FIM_ETAPA) {
				Reguladora.finalizar_etapa();
			} else if (tipo == NAO_TROCAR) {
				Reguladora.finalizar_etapa();
				Reguladora.finalizar_etapa();
			} else if (tipo == ATACAR) {
				Grafica.atualizar_territorio(origem, {"fundo" : 3});
				Grafica.atualizar_territorio(alvo, {"fundo" : 4});
				for (i=0; i<3; i++) {
					if (i<dados[0].length) {
						Grafica.dados[i].jogar(Math.round(1000*Reguladora.velocidade*(Math.random()+1/2)), dados[0][i]);
						Grafica.root[Grafica.dados[i].mc].visible = true;
					} else {
						Grafica.root[Grafica.dados[i].mc].visible = false;
					}
				}
				Reguladora.timeout(executar3, 1000*Reguladora.velocidade);
				Reguladora.timeout(executar4, 3500*Reguladora.velocidade);
				if (movidos) {
					Reguladora.timeout(executar5, 4500*Reguladora.velocidade);
				}
				if (eliminado) {
					Reguladora.timeout(executar6, 5500*Reguladora.velocidade);
				}
				
				// Sons
				if (Grafica.jogadores[Grafica.root[alvo.mc].currentFrame-1].humano) {
					(new SomAtacado).play();
				}
				if (Reguladora.velocidade>Math.random()) {
					(new SomDado).play();
				}
			} else if (tipo == MOVER && num != 0) {
				Grafica.atualizar_territorio(origem, {"delta" : -num, "aviso" : true});
				Grafica.atualizar_territorio(alvo, {"delta" : num, "fundo" : 2, "aviso" : true});
				
				// Som
				if (Reguladora.velocidade>Math.random()) {
					(new SomMover).play();
				}
			}
			
			// Atualiza parte da interface
			Grafica.campos_gerais();
		}
		
		// Lança os dados da defesa
		private function executar3(evento:TimerEvent):void {
			var i:int;
			for (i=0; i<3; i++) {
				if (i<dados[1].length) {
					Grafica.dados[3+i].jogar(Math.round(1000*Reguladora.velocidade*(Math.random()+1/2)), dados[1][i]);
					Grafica.root[Grafica.dados[3+i].mc].visible = true;
				} else {
					Grafica.root[Grafica.dados[3+i].mc].visible = false;
				}
			}
			
			// Som
			if (Reguladora.velocidade>Math.random()) {
				(new SomDado).play();
			}
		}
		
		// Atualiza os territórios após um ataque
		private function executar4(evento:TimerEvent):void {
			var temp:TextField, temp2:TextField;
			
			Grafica.atualizar_territorio(origem, {"delta" : -perdas_origem, "aviso" : true});
			Grafica.atualizar_territorio(alvo, {"delta" : -perdas_alvo, "aviso" : true});
			
			// Muda as estatíscas das perdas na interface
			if (Reguladora.ativo) {
				// Mortos em combate
				temp = Grafica.root["txt_mortos_em_combate"];
				if (Grafica.root[origem.mc].currentFrame == Reguladora.ativo.id) {
					temp.text = Reguladora.formatar_num(int(temp.text)+perdas_origem, 4);
				} else if (Grafica.root[alvo.mc].currentFrame == Reguladora.ativo.id) {
					temp.text = Reguladora.formatar_num(int(temp.text)+perdas_alvo, 4);
				}
				
				// Inimigos mortos
				temp2 = Grafica.root["txt_inimigos_mortos"];
				if (Grafica.root[alvo.mc].currentFrame == Reguladora.ativo.id) {
					temp2.text = Reguladora.formatar_num(int(temp2.text)+perdas_origem, 4);
				} else if (Grafica.root[origem.mc].currentFrame == Reguladora.ativo.id) {
					temp2.text = Reguladora.formatar_num(int(temp2.text)+perdas_alvo, 4);
				}
			}
			
			if (movidos) {
				// Move soldados do território atacante para o capturado
				Grafica.atualizar_territorio(origem, {"fundo" : 5});
				Grafica.atualizar_territorio(alvo, {"fundo" : 4});
			} else {
				// Retira os efeitos do fundo
				Grafica.atualizar_territorio(origem, {"fundo" : null});
				Grafica.atualizar_territorio(alvo, {"fundo" : null});
				
				if (Reguladora.vez.humano && origem.soldados>1) {
					// Mostra o botão de repetir ataque
					Grafica.root.bt_repetir_ataque.visible = true;
					Grafica.root.bt_repetir_ataque.x = (Grafica.root[origem.mc].x+Grafica.root[alvo.mc].x)/2;
					Grafica.root.bt_repetir_ataque.y = (Grafica.root[origem.mc].y+Grafica.root[alvo.mc].y)/2;
					Usuario.ultimo_ataque = this;
				}
			}
			
			// Sons
			if (Reguladora.velocidade>Math.random()) {
				if (perdas_origem>perdas_alvo) {
					(new SomDefesa).play();
				} else {
					(new SomAtaque).play();
				}
			}
		}
		
		// Move os soldado do território atacante para o capturado
		private function executar5(evento:TimerEvent):void {
			var dono:Jogador = Relacao.get_relacao(origem, Relacao.DONO);
			var temp:TextField, temp2:TextField;
			
			// Atualiza a interface
			temp = Grafica.root["txt_num_territorios"+String(dono.id-1)];
			temp.text = Reguladora.formatar_num(int(temp.text)+1, 2);
			temp2 = Grafica.root["txt_num_territorios"+String(Grafica.root[alvo.mc].currentFrame-1)];
			temp2.text = Reguladora.formatar_num(int(temp2.text)-1, 2);
			
			// Atualiza os territórios
			if (dono.humano) {
				Grafica.atualizar_territorio(origem, {"delta" : -movidos});
				Grafica.atualizar_territorio(alvo, {"delta" : movidos, "dono" : dono, "aviso" : true});
				if (origem.soldados>1) {
					Usuario.mover_ataque(this);
				} else {
					Grafica.atualizar_territorio(origem, {"fundo" : null});
					Grafica.atualizar_territorio(alvo, {"fundo" : null});
				}
			} else {
				Grafica.atualizar_territorio(origem, {"delta" : -movidos, "fundo" : null});
				Grafica.atualizar_territorio(alvo, {"delta" : movidos, "dono" : dono, "aviso" : true, "fundo" : null});
			}
			
			// Som
			if (Reguladora.velocidade>Math.random()) {
				(new SomMover).play();
			}
		}
		
		// Mostra o objetivo do jogador eliminado
		private function executar6(evento:TimerEvent):void {
			Grafica.root["mc_fundo_janelas"].visible = Grafica.root["mc_janela_objetivo"].visible = true;
			Grafica.root["mc_janela_objetivo"].mc_objetivo.gotoAndStop(Relacao.get_relacao(eliminado, Relacao.OBJETIVO).id);
			Reguladora.timeout(function (e:TimerEvent) {Grafica.root["mc_fundo_janelas"].visible = Grafica.root["mc_janela_objetivo"].visible = false;}, 2500*(Reguladora.velocidade+1));
			Grafica.campos_jogador(true);
		}
	}
}