package algoritmo;

import auxiliar.Conversor;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;

public class Solucao {

    private int idSolucao; //necessário para identificar as fotos (para salvar a imagem)

    private double utilidade = 0;//diminui cada vez que a regiao eh fotografada de novo
    private int qtdPixelsComObjetivo;//qtdPixelsComObjetivo na imagem (fitness da solução)
    private double fitness;//qtd de pixels com objetivo * utilidade

    /*Estes attributos são impportantes para comunicação - módulo otimização*/
    private BufferedImage fotoRegiao;
    private double[] vetorIndicacaoPosicaoQuadrante1; //escala em metros
    private double[] vetorIndicacaoPosicaoQuadrante2;
    private double[] vetorIndicacaoPosicaoQuadrante3;
    private double[] vetorIndicacaoPosicaoQuadrante4;
    //ponto de origem do vetor de indicação, reresenta o ponto de distância mínima entre o agente e o tubo
    private double[] origemVetorIndicacaoPosicaoQuadrante1;//escala em metros (espaço de busca)
    private double[] origemVetorIndicacaoPosicaoQuadrante2;
    private double[] origemVetorIndicacaoPosicaoQuadrante3;
    private double[] origemVetorIndicacaoPosicaoQuadrante4;
    private boolean quadrante1Fotografado = false;// indica se já foi escolhido para fotografa
    private boolean quadrante2Fotografado = false;
    private boolean quadrante3Fotografado = false;
    private boolean quadrante4Fotografado = false;
	
    /*Estes attributos são impportantes para comunicação - módulo exploração*/
	private double[] posicao; //posicão do agente quando a imagem foi tirada (escala em metros)
    private double raioDaAreaDaImagemEmMetros;//escala em metros
    

	public Solucao(int idSolucao){
        this.idSolucao = idSolucao;
		this.fitness=0;
		this.posicao= new double[2];
        this.qtdPixelsComObjetivo = 0;
        this.utilidade = 0;
        this.vetorIndicacaoPosicaoQuadrante1 = new double[2];
        this.origemVetorIndicacaoPosicaoQuadrante1 =  new double[2];
        
        this.vetorIndicacaoPosicaoQuadrante2 = new double[2];
        this.origemVetorIndicacaoPosicaoQuadrante2 =  new double[2];
        
        this.vetorIndicacaoPosicaoQuadrante3 = new double[2];
        this.origemVetorIndicacaoPosicaoQuadrante3 =  new double[2];
        
        this.vetorIndicacaoPosicaoQuadrante4 = new double[2];
        this.origemVetorIndicacaoPosicaoQuadrante4 =  new double[2];

	}


	public double getFitness() {
		return fitness;
	}
	
	public void setFitness(double fitness) {
		this.fitness = fitness;
	}
	
	public double[] getPosicao() {
		return posicao;
	}
	
	public void setPosicao(double[] posicao) {
		this.posicao = posicao;
	}

    public BufferedImage getFotoRegiao() {
        return fotoRegiao;
    }

    public void setFotoRegiao(BufferedImage fotoRegiao) {
        this.fotoRegiao = fotoRegiao;
    }

    public double[] getOrigemVetorIndicacaoPosicaoQuadrante1() {
        return origemVetorIndicacaoPosicaoQuadrante1;
    }

    public void setOrigemVetorIndicacaoPosicaoQuadrante1(double[] origemVetorIndicacaoPosicao) {
        this.origemVetorIndicacaoPosicaoQuadrante1 = origemVetorIndicacaoPosicao;
    }

    public int getQtdPixelsComObjetivo() {
        return qtdPixelsComObjetivo;
    }

    public void setQtdPixelsComObjetivo(int qtdPixelsComObjetivo) {
        this.qtdPixelsComObjetivo = qtdPixelsComObjetivo;
    }

    public double[] getVetorIndicacaoPosicaoQuadrante1() {
        return vetorIndicacaoPosicaoQuadrante1;
    }

    public void setVetorIndicacaoPosicaoQuadrante1(double[] vetorIndicacaoPosicao) {
        this.vetorIndicacaoPosicaoQuadrante1 = vetorIndicacaoPosicao;
    }

    public double getRaioDaAreaDaImagemEmMetros() {
        return raioDaAreaDaImagemEmMetros;
    }

    public void setRaioDaAreaDaImagemEmMetros(double raioDaAreaDaImagem) {
        this.raioDaAreaDaImagemEmMetros = raioDaAreaDaImagem;
    }

    public int getIdSolucao() {
        return idSolucao;
    }

    public double[] getOrigemVetorIndicacaoPosicaoQuadrante2() {
        return origemVetorIndicacaoPosicaoQuadrante2;
    }

    public void setOrigemVetorIndicacaoPosicaoQuadrante2(double[] origemVetorIndicacaoPosicaoQuadrante2) {
        this.origemVetorIndicacaoPosicaoQuadrante2 = origemVetorIndicacaoPosicaoQuadrante2;
    }

    public double[] getOrigemVetorIndicacaoPosicaoQuadrante3() {
        return origemVetorIndicacaoPosicaoQuadrante3;
    }

    public void setOrigemVetorIndicacaoPosicaoQuadrante3(double[] origemVetorIndicacaoPosicaoQuadrante3) {
        this.origemVetorIndicacaoPosicaoQuadrante3 = origemVetorIndicacaoPosicaoQuadrante3;
    }

    public double[] getOrigemVetorIndicacaoPosicaoQuadrante4() {
        return origemVetorIndicacaoPosicaoQuadrante4;
    }

    public void setOrigemVetorIndicacaoPosicaoQuadrante4(double[] origemVetorIndicacaoPosicaoQuadrante4) {
        this.origemVetorIndicacaoPosicaoQuadrante4 = origemVetorIndicacaoPosicaoQuadrante4;
    }

    public double[] getVetorIndicacaoPosicaoQuadrante2() {
        return vetorIndicacaoPosicaoQuadrante2;
    }

    public void setVetorIndicacaoPosicaoQuadrante2(double[] vetorIndicacaoPosicaoQuadrante2) {
        this.vetorIndicacaoPosicaoQuadrante2 = vetorIndicacaoPosicaoQuadrante2;
    }

    public double[] getVetorIndicacaoPosicaoQuadrante3() {
        return vetorIndicacaoPosicaoQuadrante3;
    }

    public void setVetorIndicacaoPosicaoQuadrante3(double[] vetorIndicacaoPosicaoQuadrante3) {
        this.vetorIndicacaoPosicaoQuadrante3 = vetorIndicacaoPosicaoQuadrante3;
    }

    public double[] getVetorIndicacaoPosicaoQuadrante4() {
        return vetorIndicacaoPosicaoQuadrante4;
    }

    public void setVetorIndicacaoPosicaoQuadrante4(double[] vetorIndicacaoPosicaoQuadrante4) {
        this.vetorIndicacaoPosicaoQuadrante4 = vetorIndicacaoPosicaoQuadrante4;
    }

    public boolean isQuadrante1Fotografado() {
        return quadrante1Fotografado;
    }

    public void setQuadrante1Fotografado(boolean quadrante1Fotografado) {
        this.quadrante1Fotografado = quadrante1Fotografado;
    }

    public boolean isQuadrante2Fotografado() {
        return quadrante2Fotografado;
    }

    public void setQuadrante2Fotografado(boolean quadrante2Fotografado) {
        this.quadrante2Fotografado = quadrante2Fotografado;
    }

    public boolean isQuadrante3Fotografado() {
        return quadrante3Fotografado;
    }

    public void setQuadrante3Fotografado(boolean quadrante3Fotografado) {
        this.quadrante3Fotografado = quadrante3Fotografado;
    }

    public boolean isQuadrante4Fotografado() {
        return quadrante4Fotografado;
    }

    public void setQuadrante4Fotografado(boolean quadrante4Fotografado) {
        this.quadrante4Fotografado = quadrante4Fotografado;
    }

    public void salvarRegiaoMapeada(int idAgente){
        try{
                ImageIO.write( fotoRegiao, "jpg", new File("images\\Sensor Fotografico\\FotoDeRegiao-Ag"+idAgente+"foto" + idSolucao+ ".png"));
            } catch (Exception e) {
                 e.printStackTrace();
            }
    }

	public void clear(){
		fitness=-1;
		posicao= new double[2];	
	}

    public double[] getMelhorPosicaoQuadrante1(){
        double[] melhorPosicao = new double[2];
        melhorPosicao[0] = origemVetorIndicacaoPosicaoQuadrante1[0]+2*vetorIndicacaoPosicaoQuadrante1[0];
        melhorPosicao[1] = origemVetorIndicacaoPosicaoQuadrante1[1]+2*vetorIndicacaoPosicaoQuadrante1[1];
        
        return melhorPosicao;
    }

    public double[] getMelhorPosicaoQuadrante2(){
        double[] melhorPosicao = new double[2];
        melhorPosicao[0] = origemVetorIndicacaoPosicaoQuadrante2[0]+2*vetorIndicacaoPosicaoQuadrante2[0];
        melhorPosicao[1] = origemVetorIndicacaoPosicaoQuadrante2[1]+2*vetorIndicacaoPosicaoQuadrante2[1];

        return melhorPosicao;
    }

    public double[] getMelhorPosicaoQuadrante3(){
        double[] melhorPosicao = new double[2];
        melhorPosicao[0] = origemVetorIndicacaoPosicaoQuadrante3[0]+2*vetorIndicacaoPosicaoQuadrante3[0];
        melhorPosicao[1] = origemVetorIndicacaoPosicaoQuadrante3[1]+2*vetorIndicacaoPosicaoQuadrante3[1];

        return melhorPosicao;
    }

    public double[] getMelhorPosicaoQuadrante4(){
        double[] melhorPosicao = new double[2];
        melhorPosicao[0] = origemVetorIndicacaoPosicaoQuadrante4[0]+2*vetorIndicacaoPosicaoQuadrante4[0];
        melhorPosicao[1] = origemVetorIndicacaoPosicaoQuadrante4[1]+2*vetorIndicacaoPosicaoQuadrante4[1];

        return melhorPosicao;
    }

    public double[] gerarPosicaoAproximada(){
        double[] melhorPosicao = new double[2];
        double valorAleatorio1 = (raioDaAreaDaImagemEmMetros)*Math.random();
        double valorAleatorio2 = valorAleatorio1*Math.random()-(valorAleatorio1 / 2);
        int quadrante = 1+(int)(Math.random() * 3);// numero de 1 a 4
        if(quadrante == 1){
            melhorPosicao[0] = origemVetorIndicacaoPosicaoQuadrante1[0]+valorAleatorio2*vetorIndicacaoPosicaoQuadrante1[0];
            melhorPosicao[1] = origemVetorIndicacaoPosicaoQuadrante1[1]+valorAleatorio2*vetorIndicacaoPosicaoQuadrante1[1];
            System.out.println("vetorLbestEmMetrosQuadrante1 (Aleatorio):" + valorAleatorio2*vetorIndicacaoPosicaoQuadrante1[0] + "," + valorAleatorio2*vetorIndicacaoPosicaoQuadrante1[1]);
        }
        else if(quadrante == 2){
            melhorPosicao[0] = origemVetorIndicacaoPosicaoQuadrante2[0]+valorAleatorio2*vetorIndicacaoPosicaoQuadrante2[0];
            melhorPosicao[1] = origemVetorIndicacaoPosicaoQuadrante2[1]+valorAleatorio2*vetorIndicacaoPosicaoQuadrante2[1];
            System.out.println("vetorLbestEmMetrosQuadrante2 (Aleatorio):" + valorAleatorio2*vetorIndicacaoPosicaoQuadrante2[0] + "," + valorAleatorio2*vetorIndicacaoPosicaoQuadrante2[1]);
        }
        else if(quadrante == 3){
            melhorPosicao[0] = origemVetorIndicacaoPosicaoQuadrante3[0]+valorAleatorio2*vetorIndicacaoPosicaoQuadrante3[0];
            melhorPosicao[1] = origemVetorIndicacaoPosicaoQuadrante3[1]+valorAleatorio2*vetorIndicacaoPosicaoQuadrante3[1];
            System.out.println("vetorLbestEmMetrosQuadrante3 (Aleatorio):" + valorAleatorio2*vetorIndicacaoPosicaoQuadrante3[0] + "," + valorAleatorio2*vetorIndicacaoPosicaoQuadrante3[1]);
        }
        else if(quadrante == 4){
            melhorPosicao[0] = origemVetorIndicacaoPosicaoQuadrante4[0]+valorAleatorio2*vetorIndicacaoPosicaoQuadrante4[0];
            melhorPosicao[1] = origemVetorIndicacaoPosicaoQuadrante4[1]+valorAleatorio2*vetorIndicacaoPosicaoQuadrante4[1];
            System.out.println("vetorLbestEmMetrosQuadrante4 (Aleatorio):" + valorAleatorio2*vetorIndicacaoPosicaoQuadrante4[0] + "," + valorAleatorio2*vetorIndicacaoPosicaoQuadrante4[1]);
        }
        

        return melhorPosicao;
    }

    public double[] gerarPosicaoAoRedor(){
         int angulo = (int) Math.round(Math.random() * 360);
         angulo = (int) Conversor.ajustarAnguloParaEscala_0_360(angulo);
         double raioDeslocamento = raioDaAreaDaImagemEmMetros*2;//Rd = 2*RaioSensor

         double[] pos = Conversor.coordPolarParaCartesiana(raioDeslocamento, angulo);
         double[] resposta = new double[2];
         resposta[0] = this.posicao[0]+pos[0];
         resposta[1] = this.posicao[1]+pos[1];
         return resposta;
    }

  
    public void calculaFitness(){
        fitness = qtdPixelsComObjetivo+utilidade;
    }

    public double getUtilidade() {
        return utilidade;
    }

    public void setUtilidade(double utilidade) {
        this.utilidade = utilidade;
    }

   public boolean equals(Solucao sol){
       if(sol.getIdSolucao() == this.idSolucao)
           return true;
       else
           return false;
   }

   public boolean equals(double[] pos){

       if(pos[0] == posicao[0] && pos[1] == posicao[1])
            return true;
        else
            return false;
   }
}
