/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package algoritmo;

import java.util.Vector;

/**
 *
 * @author Marília
 */
public class ConjuntoDeSolucoes {
    private Vector<Solucao> solucoes;
    private int numeroMaxDeSolucoesParaTransmitir;
    private Solucao solucaoPbest;
    private Solucao solucaoLbest;
    private Vector<Solucao> solucoesLbestDescartadas;

    //Construtores
    public ConjuntoDeSolucoes(){
       numeroMaxDeSolucoesParaTransmitir = 3;
       solucoes = new Vector<Solucao>();
       solucoesLbestDescartadas = new Vector<Solucao>();

       solucaoPbest = new Solucao(0);
       solucaoPbest.setFotoRegiao(null);
       solucaoPbest.setOrigemVetorIndicacaoPosicaoQuadrante1(null);
       solucaoPbest.setVetorIndicacaoPosicaoQuadrante1(null);

       solucaoLbest = new Solucao(1);
       solucaoLbest.setFotoRegiao(null);
       solucaoLbest.setOrigemVetorIndicacaoPosicaoQuadrante1(null);
       solucaoLbest.setVetorIndicacaoPosicaoQuadrante1(null);
	}

	public ConjuntoDeSolucoes(int numeroMaxDeSolucoesParaTransmitir){
       this.numeroMaxDeSolucoesParaTransmitir = numeroMaxDeSolucoesParaTransmitir;
       solucoes = new Vector<Solucao>();
       solucoesLbestDescartadas = new Vector<Solucao>();
       
       solucaoPbest = new Solucao(0);
       solucaoPbest.setFotoRegiao(null);
       //solucaoPbest.setOrigemVetorIndicacaoPosicaoQuadrante1(null);
       //solucaoPbest.setVetorIndicacaoPosicaoQuadrante1(null);

       solucaoLbest = new Solucao(1);
       solucaoLbest.setFotoRegiao(null);
       //solucaoLbest.setOrigemVetorIndicacaoPosicaoQuadrante1(null);
       //solucaoLbest.setVetorIndicacaoPosicaoQuadrante1(null);
	}
    
    //Métodos
	public void inserirSolucao(Solucao solucao){
		solucoes.add(solucao);
	}

	public void removerSolucao(Solucao solucao){
		solucoes.remove(solucao);
	}

    public void removerTodos(){
        solucoes.removeAllElements();
    }

    //Detecta se existe o solucao cuja area  engloba a posição passada como parametro
	public boolean existeSolucao(double[] posicao){
		double[] posicaoSolucao;

		for(int i = 0; i< solucoes.size(); i++){
			posicaoSolucao = solucoes.get(i).getPosicao();


			if(posicaoSolucao[0]==posicao[0] && posicaoSolucao[1]==posicao[1]){
				return true;
			}
		}
		return false;
	}

    //Testa se a posicão tem proximidade menor que "distanciaMinimaPermitida" em relação às outras soluções
    public boolean testarDistanciaMinimaPermitidaEntrePontos(double[] posicao, double distanciaPermitida, boolean consideraRaioDaSolucaoTestada){
        double[] posicaoDestino = posicao;
        double[] localJaVisitado;
        double distanciaEntreOsPontos;
        double distanciaMinimaPermitida;
        double raioDaSolucao = 0;

        for (int idSolucao = 0;  idSolucao <  solucoes.size();  idSolucao++) {
                localJaVisitado = solucoes.get(idSolucao).getPosicao();
                if(consideraRaioDaSolucaoTestada)
                    raioDaSolucao =   solucoes.get(idSolucao).getRaioDaAreaDaImagemEmMetros();

                distanciaMinimaPermitida = distanciaPermitida +raioDaSolucao;

                distanciaEntreOsPontos = Math.sqrt(
                                                Math.pow( Math.abs(localJaVisitado[0] - posicaoDestino[0]) , 2)
                                                +
                                                Math.pow( Math.abs(localJaVisitado[1] - posicaoDestino[1]) , 2) );
                if ( distanciaEntreOsPontos < distanciaMinimaPermitida){
                     System.out.println("\t Agente testa Distancia ate solucao "+ idSolucao+ "("+localJaVisitado[0]+","+localJaVisitado[1]+"): "+distanciaEntreOsPontos+" < "+distanciaMinimaPermitida+" --> "+true);
                   return true; //posicao ja avaliada
                }
        }

        return false;
    }

    public void atualizarUtilidades(Solucao solucaoNova, double distanciaPermitida, boolean consideraRaioDaSolucaoTestada){
        double[] posicaoDaSolucaoNova = solucaoNova.getPosicao();
        double[] localJaVisitado;
        double distanciaEntreOsPontos;
        double distanciaMinimaPermitida;
        double raioDaSolucao = 0;
        
        Solucao solucao;
        //Lbest e Pbest estão nesse bolo que vai ser atualizado...
        for (int idSolucao = 0;  idSolucao <  solucoes.size();  idSolucao++) {
                solucao = solucoes.get(idSolucao);
                localJaVisitado = solucao.getPosicao();
                if(consideraRaioDaSolucaoTestada)
                    raioDaSolucao =   solucao.getRaioDaAreaDaImagemEmMetros();

                distanciaMinimaPermitida = distanciaPermitida +raioDaSolucao;

                distanciaEntreOsPontos = Math.sqrt(
                                                Math.pow( Math.abs(localJaVisitado[0] - posicaoDaSolucaoNova[0]) , 2)
                                                +
                                                Math.pow( Math.abs(localJaVisitado[1] - posicaoDaSolucaoNova[1]) , 2) );
                if ( distanciaEntreOsPontos < distanciaMinimaPermitida){
                    //utilidade <- utilidadeAtual - (distanciaMinimaPermitida - distanciaEntreOsPontos)
                    solucao.setUtilidade(  solucao.getUtilidade()-(distanciaMinimaPermitida - distanciaEntreOsPontos)  );
                    solucao.calculaFitness();//atualiza fitness
                    solucaoNova.setUtilidade(  solucaoNova.getUtilidade()-(distanciaMinimaPermitida - distanciaEntreOsPontos)  );

                }
        }

        //testa solucao Lbest
        /*
        localJaVisitado = solucaoLbest.getPosicao();
        if(consideraRaioDaSolucaoTestada)
            raioDaSolucao =   solucaoLbest.getRaioDaAreaDaImagemEmMetros();

        distanciaMinimaPermitida = distanciaPermitida +raioDaSolucao;

        distanciaEntreOsPontos = Math.sqrt(
                                        Math.pow( Math.abs(localJaVisitado[0] - posicaoDaSolucaoNova[0]) , 2)
                                        +
                                        Math.pow( Math.abs(localJaVisitado[1] - posicaoDaSolucaoNova[1]) , 2) );
        if ( distanciaEntreOsPontos < distanciaMinimaPermitida){
             solucaoLbest.setUtilidade(  solucaoLbest.getUtilidade()-(distanciaMinimaPermitida - distanciaEntreOsPontos)  );
             solucaoNova.setUtilidade(  solucaoNova.getUtilidade()-(distanciaMinimaPermitida - distanciaEntreOsPontos)  );
        }
        */

    }
    //Detecta o solucao cuja area  engloba a posição passada como parametro
    public Solucao buscarSolucao(double[] posicao){
		
		return null;
	}

	public Solucao get(int index){
		return solucoes.get(index);
	}

    //n últimos locais avaliados
    public ConjuntoDeSolucoes getUltimosLocaisAvaliados(){
        ConjuntoDeSolucoes ultimasSolucoesAvaliadas =  new ConjuntoDeSolucoes();
        int ultimaPosicao = solucoes.size()-1;
        for(int i=0;i<numeroMaxDeSolucoesParaTransmitir;i++){
            if(ultimaPosicao-i >=0)
                ultimasSolucoesAvaliadas.inserirSolucao( solucoes.get(ultimaPosicao-i) );
        }
        return ultimasSolucoesAvaliadas;

    }

    public boolean elegeOutroLbestDaMemoria(){
        Solucao solucao;
        boolean destinoValidoQuadrante1;
        boolean destinoValidoQuadrante2;
        boolean destinoValidoQuadrante3;
        boolean destinoValidoQuadrante4;
        boolean novoLbestFoiDeterminado = false;

        solucoesLbestDescartadas.add(solucaoLbest);//descarta o lbestAtual
        for (int idSolucao = 0;  idSolucao <  solucoes.size();  idSolucao++) {
                solucao = solucoes.get(idSolucao);
                if(!solucoesDescartadasContem(solucao)){//solucoes ja descartadas nao sao elegidas, nem solucoes que todos os quadrantes ja foram fotgrafados
                
                    destinoValidoQuadrante1 = (!solucao.isQuadrante1Fotografado()) && (solucao.getVetorIndicacaoPosicaoQuadrante1()[0]!=0 || solucao.getVetorIndicacaoPosicaoQuadrante1()[1]!=0);
                    destinoValidoQuadrante2 = (!solucao.isQuadrante2Fotografado()) && (solucao.getVetorIndicacaoPosicaoQuadrante2()[0]!=0 || solucao.getVetorIndicacaoPosicaoQuadrante2()[1]!=0);
                    destinoValidoQuadrante3 = (!solucao.isQuadrante3Fotografado()) && (solucao.getVetorIndicacaoPosicaoQuadrante3()[0]!=0 || solucao.getVetorIndicacaoPosicaoQuadrante3()[1]!=0);
                    destinoValidoQuadrante4 = (!solucao.isQuadrante4Fotografado()) && (solucao.getVetorIndicacaoPosicaoQuadrante4()[0]!=0 || solucao.getVetorIndicacaoPosicaoQuadrante4()[1]!=0);

                    if(destinoValidoQuadrante1 || destinoValidoQuadrante2 || destinoValidoQuadrante3 || destinoValidoQuadrante4 ){
                        solucaoLbest = solucao;
                        novoLbestFoiDeterminado = true;
                        break;
                    }
                    else{
                        solucoesLbestDescartadas.add(solucao);//descarta solucao que nao serve
                    }
                }
        }
        return novoLbestFoiDeterminado;
    }

    public boolean solucoesDescartadasContem(Solucao solucao){
        Solucao descartada;
        for(int i=0;i<solucoesLbestDescartadas.size();i++){
            descartada = solucoesLbestDescartadas.get(i);
            if(descartada.getPosicao()[0] == solucao.getPosicao()[0] && descartada.getPosicao()[1] == solucao.getPosicao()[1])
                return true;
        }
        return false;
    }
    public void elegeMelhorSolucaoDescartadaComoLbest(){
        Solucao descartada;
        double maiorFitness=-99999;
        int idMaiorFit = 0;
        for(int i=0;i<solucoesLbestDescartadas.size();i++){
            descartada = solucoesLbestDescartadas.get(i);
            descartada.calculaFitness();

            if(descartada.getFitness() > maiorFitness){
                maiorFitness = descartada.getFitness();
                idMaiorFit = i;
            }
        }
        solucaoLbest = solucoesLbestDescartadas.get(idMaiorFit);
    }

	public String toString(){
		String retorno = "Conjunto de Solucoes:";
		for(int i =0; i<solucoes.size();i++){
			retorno += "\n"+ solucoes.get(i).toString();
		}
		return retorno;
	}

    public int getNumeroMaxDeSolucoesParaTransmitir() {
        return numeroMaxDeSolucoesParaTransmitir;
    }

    public void setNumeroMaxDeSolucoesParaTransmitir(int numeroMaxDeSolucoesParaTransmitir) {
        this.numeroMaxDeSolucoesParaTransmitir = numeroMaxDeSolucoesParaTransmitir;
    }


    public int getNumSolucoes(){
		return solucoes.size();
	}

    public Solucao getSolucaoLbest() {
        return solucaoLbest;
    }

    public void setSolucaoLbest(Solucao solucaoLbest) {
        this.solucaoLbest = solucaoLbest;
    }

    public Solucao getSolucaoPbest() {
        return solucaoPbest;
    }

    public void setSolucaoPbest(Solucao solucaoPbest) {
        this.solucaoPbest = solucaoPbest;
    }
    
}
