package webCAPPCombd;

import comHttp.RequisitorHttp;
import infoUsinagem.*;
import java.util.StringTokenizer;
import java.util.Properties;

public class DeterminadorDeTecUsinagem{

  private static final String URI_DO_SERVLET = ":8080/combdServlet/comhttpservlet";
  private static final String URL_DOS_DADOS = "http://www.coroguide.com/CuttingDataModule/CDMTurning.asp";


  //Constantes de tipo de pastilha usada em torneamento.
  public static final int TG_PASTILHA_COMUM = 0;
  public static final int TG_PASTILHA_REDONDA = 1;
  //Constantes de tipo de torneamento.
  public static final int TG_ACABAMENTO_EXTREMO = 0;
  public static final int TG_ACABAMENTO = 1;
  public static final int TG_USINAGEM_MEDIA = 2;
  public static final int TG_DESBASTE_LEVE = 3;
  public static final int TG_DESBASTE = 4;
  public static final int TG_DESBASTE_PESADO = 5;
  //Constante de valores fixos.
  private static final String TG_PADRAO_VALOR = "AISI/SAE";
  private static final String TG_UNIDADES_VALOR = "0";///padrão métrico.
  private static final String TG_COMANDO_DE_CALCULO_VALOR = "Calculate";
  //Variáveis fixas.
  private static final String TG_PADRAO = "cboMtrlstnd";
  private static final String TG_UNIDADES = "optMetric";
  private static final String TG_COMANDO_DE_CALCULO = "cmdCalc";
  //Constante dos nomes das variáveis.
  private static final String TG_TIPO_PASTILHA = "optTurning";
  private static final String TG_TIPO_TORNEAMENTO = "optType";
  private static final String TG_MATERIAL = "cboMaterial";
  private static final String TG_CLASSE = "cboGrade";
  private static final String TG_Kr_OU_IC = "txtKriC";
  private static final String TG_RAIO_PONTA = "txtre";
  private static final String TG_AVANCO = "txtfn";
  private static final String TG_PROFUNDIDADE_CORTE = "txtap";
  private static final String TG_Dm1 = "txtdmin";
  private static final String TG_Dm2 = "txtdmax";
  private static final String TG_Lz = "txtlz";
  private static final String TG_MAX_RPM = "txtMaxn";
  private static final String TG_TEMPO_VIDA = "txtt";
  //Constantes das variaveis de retorno.
  private static final String TG_VC = "lblVcStartStop";
  private static final String TG_RPM = "lbln";
  private static final String TG_TAXA_REMOCAO = "lblQ";
  private static final String TG_NUM_PASSES = "txtnap";
  private static final String TG_TEMPO_PASSE = "lblTc";
  private static final String TG_POTENCIA = "lblPc";
  private static final String TG_RUGOSIDADE = "lblRa";

  private RequisitorHttp requisitor;

  public DeterminadorDeTecUsinagem(String urlDoServidor){

    requisitor =  new RequisitorHttp(urlDoServidor + URI_DO_SERVLET);
  }


  protected final TecnologiaDeUsinagem calculaCondicaoDeUsinagem_Torneamento(
    int tipoPastilha, int tipoTorneamento,
    String material, FerramentaTorneamento f,
    double ap, double fn, double dm1, double dm2, double lz, int maxRPM, int tempoVida){

    Properties prop = new Properties();
    //fixas.
    prop.setProperty(TG_PADRAO, TG_PADRAO_VALOR);
    prop.setProperty(TG_UNIDADES, TG_UNIDADES_VALOR);
    prop.setProperty(TG_COMANDO_DE_CALCULO, TG_COMANDO_DE_CALCULO_VALOR);
    //variaveis.
    prop.setProperty(TG_TIPO_PASTILHA, String.valueOf(tipoPastilha));
    prop.setProperty(TG_TIPO_TORNEAMENTO, String.valueOf(tipoTorneamento));
    prop.setProperty(TG_MATERIAL, material);
    prop.setProperty(TG_CLASSE, f.getClasse());
    if(tipoPastilha == TG_PASTILHA_COMUM){
      //Busca o angulo Kr(cut_out).
      prop.setProperty(TG_Kr_OU_IC, String.valueOf(f.getCutOut()));
      prop.setProperty(TG_RAIO_PONTA, String.valueOf(f.getRaioPonta()));
    }
    else{//Busca o diametro da ferramenta redonda.
      prop.setProperty(TG_Kr_OU_IC, String.valueOf(f.getCompArestaDeCorte()));
    }
    prop.setProperty(TG_AVANCO, String.valueOf(fn));
    prop.setProperty(TG_PROFUNDIDADE_CORTE, String.valueOf(ap));
    prop.setProperty(TG_Dm1, String.valueOf(dm1));
    prop.setProperty(TG_Dm2, String.valueOf(dm2));
    prop.setProperty(TG_Lz, String.valueOf(lz));
    prop.setProperty(TG_MAX_RPM, String.valueOf(maxRPM));
    prop.setProperty(TG_TEMPO_VIDA, String.valueOf(tempoVida));

    Properties resposta = requisitor.requisitaHttpVars(URL_DOS_DADOS, prop);

    StringTokenizer strVc = new StringTokenizer(resposta.getProperty(TG_VC), " -");
    StringTokenizer strRPM = new StringTokenizer(resposta.getProperty(TG_RPM), " -");

    return new TecnologiaDeUsinagem(ap, fn,
                                    strVc.hasMoreTokens() ? strVc.nextToken(): null,//vc_max
                                    strVc.hasMoreTokens() ? strVc.nextToken(): null,
                                    strRPM.hasMoreTokens() ? strRPM.nextToken(): null,//RPM_max
                                    strRPM.hasMoreTokens() ? strRPM.nextToken(): null,
                                    resposta.getProperty(TG_TAXA_REMOCAO),
                                    resposta.getProperty(TG_NUM_PASSES),
                                    resposta.getProperty(TG_TEMPO_PASSE),
                                    resposta.getProperty(TG_POTENCIA),
                                    resposta.getProperty(TG_RUGOSIDADE)
                                    );
  }//calculaCondicaoDeUsinagem_Torneamento


  protected TecnologiaDeUsinagem[] calculaArrayTecnologiaDeUsinagem(final int tipoTorneamento,
    final String material, final Ferramenta f, final double dm1, final double dm2,
    final double lz, final int maxRPM, final int tempoVida, final CalculoDeRestricao calc){

    final FerramentaTorneamento ferramenta = f instanceof FerramentaUtilizada ?
        (FerramentaTorneamento)((FerramentaUtilizada)f).getFerramenta() :
        (FerramentaTorneamento)f;

    final int tipoPastilha;
    switch(ferramenta.getFormatoPastilha()){//pega o tipo de pastilha.

      case 'R': case 'r':
        tipoPastilha = this.TG_PASTILHA_REDONDA; break;

      case 'C': case 'c':
      case 'D': case 'd':
      case 'K': case 'k':
      case 'S': case 's':
      case 'T': case 't':
      case 'V': case 'v':
      case 'W': case 'w':
        tipoPastilha = TG_PASTILHA_COMUM; break;

      default:
        throw new RuntimeException("Tipo de pastilha inválido da ferramenta:" + f);
    }

    int i;
    double ap;
    final TecnologiaDeUsinagem[]  arrayTec=//Calcula tamanho do array necessário.
        new TecnologiaDeUsinagem[(int)((ferramenta.getMax_ap()-ferramenta.getMin_ap())/0.1)];

    final Contador contador = new Contador();

    for(i=0, ap = ferramenta.getMin_ap(); i < arrayTec.length; i++, ap+= 0.1){

      final int iAtual = i;
      final double apAtual = ap;

      new java.lang.Thread(){

        double fn = ferramenta.getMax_fn();
        double ap = apAtual;
        int i = iAtual;
        TecnologiaDeUsinagem temp = null;

        public void run(){

          do {

            temp = calculaCondicaoDeUsinagem_Torneamento(tipoPastilha,
                tipoTorneamento, material, ferramenta,
                ap, fn, dm1, dm2, lz, maxRPM, tempoVida);

            fn -= 0.1;
          }
          while ( (temp == null || !calc.restricaoSatisfeita(temp)) &&
                 fn > ferramenta.getMin_fn());

          arrayTec[i] = temp;

          contador.incrementa();
          synchronized(contador){
            contador.notify();
          }

        }
      }.start();
    }

    while(contador.getValor() <  arrayTec.length){

      try{
        synchronized(contador){
          contador.wait();
        }
      }
      catch(InterruptedException e){}
    }

    return arrayTec;
  }


  public TecnologiaDeUsinagem[] calculaCondicaoDeUsinagem_TorneamentoDesbaste(int tipoTorneamento,
    String material, Ferramenta f, double dm1, double dm2,
    double lz, int maxRPM, int tempoVida, final double potenciaMaxima){

    CalculoDeRestricao calc = new CalculoDeRestricao(){

        public boolean restricaoSatisfeita(TecnologiaDeUsinagem tec){

          return tec.getPotencia() < potenciaMaxima;
        }
    };

    return calculaArrayTecnologiaDeUsinagem(tipoTorneamento, material, f, dm1, dm2, lz,
                                   maxRPM, tempoVida, calc);
  }


  public TecnologiaDeUsinagem[] calculaCondicaoDeUsinagem_TorneamentoAcabamento(int tipoTorneamento,
    String material, Ferramenta f, double dm1, double dm2,
    double lz, int maxRPM, int tempoVida, final double rugosidadeMaxima){

    CalculoDeRestricao calc = new CalculoDeRestricao(){

        public boolean restricaoSatisfeita(TecnologiaDeUsinagem tec){

          return tec.getRugosidade() < rugosidadeMaxima;
        }
    };

    return calculaArrayTecnologiaDeUsinagem(tipoTorneamento, material, f, dm1, dm2, lz,
                                   maxRPM, tempoVida, calc);
  }
}


/* Classe utilizada para a contagem sincronizada entre as Threads que
 que repartem o trabalho de busca da condição de usinagem. */
class Contador{

  int i = 0;

  synchronized void incrementa(){

    i++;
  }

  int getValor(){

    return i;
  }
}
