/**
 * \ingroup Main
 *
 * \brief Desenha uma rede no Allegro e imprime num arquivo de imagem.
 *
 * \details Esta funcao utiliza a biblioteca grafica Allegro para imprimir uma rede de Petri. 
 *
 * \param[in] rede A variavel \a rede seria a rede de Petri.
 *
 * \param[in] fname A variavel \a fname representa o nome do arquivo que sera gerado.
 *
 * \retval void a funcao retorna nada.
 *
 */
void desenha_rede(petri_t *rede, const char *fname)
{
    float ang,      /* Angulacao antre cada elemento na imagem */
          r_lugar,  /* Raio da circunferencia que representa o lugar */
          smaller,  /* A menor das dimensoes da imagem */
          x,        /* Variavel geral para representar coordenada X */
          y,        /* Variavel geral para representar coordenada Y */
          x1,       /* Variavel geral para representar coordenada X */
          y1,       /* Variavel geral para representar coordenada Y */
          x2,       /* Variavel geral para representar coordenada X */
          y2,       /* Variavel geral para representar coordenada Y */
          x3,       /* Variavel geral para representar coordenada X */
          y3,       /* Variavel geral para representar coordenada Y */
          co,       /* Variavel geral para representar cosseno */
          si;       /* Variavel geral para representar seno */

    unsigned i, q;
    lugar *a_l = rede->l;
    BITMAP *buff;
    PALETTE pal;
    flecha *a_tl = rede->tl,
           *a_lt = rede->lt;
    /* Inicializacao Allegro */
    if(install_allegro(SYSTEM_NONE, &errno, atexit)!=0)
        exit(EXIT_FAILURE);
    set_color_depth(16);
    get_palette(pal);
    buff = create_bitmap(IMG_X,IMG_Y);
    smaller = (float)IMG_X;
    if(smaller > (float)IMG_Y)
        smaller = (float)IMG_Y;
    r_lugar = smaller/4.0*(M_PI/(M_PI+(float)rede->total_l));
    if(buff == NULL)
    {
        printf("Could not create buffer!\n");
        exit(EXIT_FAILURE);
    }
    /* Desenho propriamente dito */

    if(rede->total_l > rede->total_t)
        ang = M_PI/rede->total_l;
    else
        ang = M_PI/rede->total_t;
    if(DEBUG == B || DEBUG == D) printf("Desenhando %u lugares e %u transicoes espacados entre si %.2fº...\n", rede->total_l, rede->total_t, ang*180.0/M_PI);

    /* Desenhando os lugares  */
    for(i=0;i<rede->total_l;i++)
    {
        a_l = buscarLugarPos(rede->l, i);
        q = 0;
        if(a_l != NULL)
            q = a_l->qtd;
        x = IMG_X/2.0 + (IMG_X/2.0 - r_lugar)*cos(2*i*ang);
        y = IMG_Y/2.0 + (IMG_Y/2.0 - r_lugar)*sin(2*i*ang);
        circle(buff, x, y, r_lugar, CORBRANCO);
        textprintf_ex(buff, font, x, y, CORVERDE, CORPRETO, "%u", q);
        if(DEBUG == B || DEBUG == D) printf("L%u(%u) (posicionada %.2fº)\n", i, q, ang*(2*i)*180.0/M_PI);
        textprintf_ex(buff, font, x, y - r_lugar, CORVERDE, CORPRETO, "L%u", i);
    }

    /* Desenhando as transicoes  */
    for(i=0;i<rede->total_t;i++)
    {
        x = IMG_X/2.0 + (IMG_X/2.0 - r_lugar)*cos((2*i+1)*ang);
        y = IMG_Y/2.0 + (IMG_Y/2.0 - r_lugar)*sin((2*i+1)*ang);
        line(buff, x, y+r_lugar, x, y-r_lugar, CORBRANCO);
        if(DEBUG == B || DEBUG == D) printf("T%u (posicionado %.2fº)\n", i, ang*(2*i+1)*180.0/M_PI);
        textprintf_ex(buff, font, x, y - r_lugar, CORVERDE, CORPRETO, "T%u", i);
    }

    /* Desenhando as flechas */
    while(a_tl != NULL)
    {
        i = a_tl->de;
        x1 = IMG_X/2.0 + (IMG_X/2.0 - r_lugar)*cos((2*i+1)*ang);
        y1 = IMG_Y/2.0 + (IMG_Y/2.0 - r_lugar)*sin((2*i+1)*ang);
        i = a_tl->para;
        x = IMG_X/2.0 + (IMG_X/2.0 - r_lugar)*cos(2*i*ang);
        y = IMG_Y/2.0 + (IMG_Y/2.0 - r_lugar)*sin(2*i*ang);
        co = lcos(x1,y1,x,y);
        si = lsin(x1,y1,x,y);
        x -= r_lugar*co;
        y -= r_lugar*si;
        line(buff, x1, y1, x, y, CORBRANCO);
        textprintf_ex(buff, font, (x+x1)/2, (y+y1)/2, CORVERDE, CORPRETO, "%u", a_tl->tk);
        x2 = x - (r_lugar / 4) * (si + co);
        y2 = y + (r_lugar / 4) * (co - si);
        x3 = x + (r_lugar / 4) * (si - co);
        y3 = y - (r_lugar / 4) * (si + co);
        triangle(buff, x, y, x2, y2, x3, y3, CORBRANCO);
        a_tl = a_tl->prox;
    }
    while(a_lt != NULL)
    {
        i = a_lt->de;
        x1 = IMG_X/2.0 + (IMG_X/2.0 - r_lugar)*cos(2*i*ang);
        y1 = IMG_Y/2.0 + (IMG_Y/2.0 - r_lugar)*sin(2*i*ang);
        i = a_lt->para;
        x = IMG_X/2.0 + (IMG_X/2.0 - r_lugar)*cos((2*i+1)*ang);
        y = IMG_Y/2.0 + (IMG_Y/2.0 - r_lugar)*sin((2*i+1)*ang);
        co = lcos(x1,y1,x,y);
        si = lsin(x1,y1,x,y);
        x1 += r_lugar*co;
        y1 += r_lugar*si;
        line(buff, x1, y1, x, y, CORBRANCO);
        textprintf_ex(buff, font, (x+x1)/2, (y+y1)/2, CORVERDE, CORPRETO, "%u", a_lt->tk);
        x2 = x - (r_lugar / 4) * (si + co);
        y2 = y + (r_lugar / 4) * (co - si);
        x3 = x + (r_lugar / 4) * (si - co);
        y3 = y - (r_lugar / 4) * (si + co);
        triangle(buff, x, y, x2, y2, x3, y3, CORBRANCO);
        a_lt = a_lt->prox;
    }
    /* Salvando Imagem */
    save_bitmap(fname, buff, pal);
    destroy_bitmap(buff);
    allegro_exit();
    if(!GIF) printf("Imagem %s salva com sucesso!\n", fname);
    return;
}
void boost_gauge(float boost, float o_boost) {
    float endy, endx;
    float tangle;
    //display the boost gauge background
    if (gaugedrawswitch == 0) {
        background(0, 0, 0);
        //image(loadImage("rground.bmp"),0,0);
        image(loadImage("bstback.bmp"),0,0);
        bar_labels();
        gaugedrawswitch = 1;
    }
    if (int(boost) >= warnBoost) {
        warn_flash();
    }
    //draw a line to rep this
    //line is 40 pixels long ... this is always the hypotenuse
    //angle formula is ...
    if (boost <= 0) { //ok
        endx = 24;
        endy = 94;
    }
    else if ((boost > 0) && (boost < 10)) {
        tangle = 9 * (boost); // 90/10 is 9
        endx = 87 - (40 * lcos(tangle));
        endy = 93 - (40 * lsin(tangle));
    }
    else if (boost == 10) {
        endx = 87;
        endy = 94 - 0;
    }
    else if ((boost > 10) && (boost < 20)) {
        tangle = 9 * (boost - 10);
        endx = 87 + (40 * lsin(tangle));
        endy = 93 - (40 * lcos(tangle));
    }
    else if (boost >= 20) {
        endx = 87 + 40;
        endy = 93;
    }
    if (abs(o_boost - boost) > 2) {
        stroke(224, 38, 41);
        line(87, 93, endx, endy);
        line(88, 93, endx, endy);
        line(86, 93, endx, endy);
        line(87, 94, endx, endy);
        line(87, 92, endx, endy);
        if ((endx + endy >= 2) || (endx + endy >= 2)) {
            stroke(0,0,0);
            line(87, 92, o_endx, o_endy);
            line(87, 94, o_endx, o_endy);
            line(86, 93, o_endx, o_endy);
            line(88, 93, o_endx, o_endy);
            line(87, 93, o_endx, o_endy);
        }

    }
    o_endx = endx;
    o_endy = endy;
    //print deg F
    //do conversion from int to string with decimal places
    /*char char_boost[7];
     fmtDouble(boost, 2, char_boost, 7);
     lcd_puts(char_boost, 65, 82, gaugeRed, mblack);*/
    //delay(200);
    //bmp_draw("bstgaug",0,0); //is this the right way to do a redraw??
    return;
}
void boost_gauge(){
  float endy, endx, o_endy, o_endx;
  float tangle;
  float boost = 0.0, o_boost = 0.0;
  //display the boost gauge background
  bmp_draw("bstgaug",0,0);
  //loop
  while (!(touch_get_cursor(&m_point))){
     //get boost reading
     boost++; //for testing
     if (int(boost) >= warnBoost){
      lcd_circle(11,10,9, gaugeRed, gaugeRed);
      delay(90);
      lcd_circle(11,10,9, gaugeRed, mblack);  
     }
     //draw a line to rep this
     //line is 40 pixels long ... this is always the hypotenuse
       //angle formula is ...
     if (boost <= 0){//ok
       endx = 24;
       endy = 64;
     }
     else if ((boost > 0) && (boost < 10)){
       tangle = 9 * (boost); // 90/10 is 9  
       endx = 64 - (40 * lcos(tangle));
       endy = 64 - (40 * lsin(tangle));
     }
     else if ((boost >= 10) && (boost < 20)){
       tangle = 9 * (boost - 10); 
       endx = 64 + (40 * lsin(tangle));
       endy = 64 - (40 * lcos(tangle));
     }
     else if (boost >= 20){
       endx = 104;
       endy = 64;
     }
   if (abs(o_boost - boost) > 2){
     stroke(224, 38, 41);
     line(64, 64, endx, endy);
     line(65, 64, endx, endy);
     line(63, 64, endx, endy);
     line(64, 65, endx, endy);
     line(64, 63, endx, endy);
   stroke(0,0,0);
     line(64, 63, o_endx, o_endy);
     line(64, 65, o_endx, o_endy);
     line(63, 64, o_endx, o_endy);
     line(65, 64, o_endx, o_endy);
     line(64, 64, o_endx, o_endy);

   }
   o_endx = endx;
   o_endy = endy;
     //print deg F
     //do conversion from int to string with decimal places
     char char_boost[7];
     fmtDouble(boost, 2, char_boost, 7);
     lcd_puts(char_boost, 65, 82, gaugeRed, mblack);
     //delay(200);
     //bmp_draw("bstgaug",0,0); //is this the right way to do a redraw??
  }
  while (touch_get_cursor(&m_point)){}
  //go to the next display if a touch is detected
  four_bar();
}
void oil_temp_gauge(float oil_temp, float o_oil_temp) {
    float endy, endx;
    float tangle;

    //display the oil temp gauge background
    if (gaugedrawswitch == 0) {
        background(0,0,0);
        image(loadImage("oilback.bmp"),0,0);
        bar_labels();
        gaugedrawswitch = 1;
    }
    //if warmed and not previously warmed then flash message
    if ( (oil_temp_startup == false) && (oil_temp >= oil_temp_warn) ) {
        //add new engine warmed code here!
    }
    //if the warn point is met flash the circle encompassing the gauge
    if (int(oil_temp) >= warnOilT) {
        warn_flash();
    }
    //draw a line to rep this
    //line is 40 pixels long ... this is always the hypotenuse
    //angle formula is ...
    if (oil_temp <= 120) { //ok
        endx = 87;
        endy = 94 + 30;
    }
    else if ((oil_temp > 120) && (oil_temp < 180)) { //not ok
        tangle = 1.5 * (oil_temp - 120); //1.5 is 90degrees/60degF or the scaling factor
        endx = 87 - (30.0 * lsin(tangle));
        endy = 94 + (30.0 * lcos(tangle));
    }
    else if (oil_temp == 180) { //necessary because trig does weird things at the 90deg's
        endx = 87 - 30;
        endy = 94;
    }
    else if ((oil_temp > 180) && (oil_temp < 240)) { //ok
        tangle = 1.5 * (oil_temp - 180);
        endx = 87 - (30 * lcos(tangle));
        endy = 94 - (30 * lsin(tangle));
    }
    else if (oil_temp == 240) {
        endx = 87;
        endy = 94 - 30;
    }
    else if ((oil_temp > 240) && (oil_temp < 300)) { //not ok
        tangle = 90 - 1.5 * (oil_temp - 240); //inverse...because we are actually looking for the angle down from 90 deg up
        endx = 87 + (30 * lcos(tangle));
        endy = 94 - (30 * lsin(tangle));
    }
    else if (oil_temp > 300) { //ok
        endx = 87 + 30;
        endy = 94;
    }
    if (abs(o_oil_temp - oil_temp) > 2) {
        stroke(224, 38, 41);
        line(87, 93, endx, endy);
        line(88, 93, endx, endy);
        line(86, 93, endx, endy);
        line(87, 94, endx, endy);
        line(87, 92, endx, endy);
        stroke(0,0,0);
        line(87, 92, o_endx, o_endy);
        line(87, 94, o_endx, o_endy);
        line(86, 93, o_endx, o_endy);
        line(88, 93, o_endx, o_endy);
        line(87, 93, o_endx, o_endy);
    }
    o_endx = endx;
    o_endy = endy;

    /*stroke(224, 38, 41);
    fill(0,0,0);
    char char_oil_temp[7];
    fmtDouble(oil_temp, 2, char_oil_temp, 7);
    text(char_oil_temp, 90, 115, 10);*/
    return;
}
void oil_temp_gauge(){
 float endy, endx, o_endx, o_endy;
 float tangle;
 //display the oil temp gauge background
 bmp_draw("oilgaug",0,0);
 float oil_temp = 120, o_oil_temp = 120;
  while (!(touch_get_cursor(&m_point))){
   //get oil temp from arduino
   oil_temp++; //for testing
   //if warmed and not previously warmed then flash message
   if ( (oil_temp_startup == false) && (oil_temp >= oil_temp_warn) ){
      oil_temp_startup = true;
      lcd_clearScreen(mblack);
      lcd_puts("Engine Warmed!",10,30,gaugeRed,mblack); 
            lcd_puts("Engine Warmed!",20,40,gaugeRed,mblack); 
                  lcd_puts("Engine Warmed!",30,50,gaugeRed,mblack); 
                        lcd_puts("Engine Warmed!",40,60,gaugeRed,mblack); 
      delay (2000);
      lcd_clearScreen(mblack);
      bmp_draw("oilgaug",0,0);
   }
   //if the warn point is met flash the circle encompassing the gauge
   if (int(oil_temp) >= warnOilT){
    lcd_circle(11,10,9, gaugeRed, gaugeRed);
    delay(90);
    lcd_circle(11,10,9, gaugeRed, mblack);  
   }
   //draw a line to rep this
   //line is 40 pixels long ... this is always the hypotenuse
     //angle formula is ...
   if (oil_temp <= 120){ //ok
     endx = 64;
     endy = 94;
   }
   else if ((oil_temp > 120) && (oil_temp < 180)){ //not ok
     tangle = 1.5 * (oil_temp - 120); //1.5 is 90degrees/60degF or the scaling factor
     endx = 64.0 - (30.0 * lsin(tangle)); 
     endy = 64.0 + (30.0 * lcos(tangle));
   }
   else if ((oil_temp >= 180) && (oil_temp < 240)){ //ok
     tangle = 1.5 * (oil_temp - 180);
     endx = 64 - (30 * lcos(tangle));
     endy = 64 - (30 * lsin(tangle));
   }
   else if ((oil_temp >= 240) && (oil_temp < 300)){ //not ok
     tangle = 90 - 1.5 * (oil_temp - 240); //inverse...because we are actually looking for the angle down from 90 deg up
     endx = 64 + (30 * lcos(tangle));
     endy = 64 - (30 * lsin(tangle));
   }
   else if (oil_temp > 300){//ok
     endx = 94;
     endy = 64;
   }
   if (abs(o_oil_temp - oil_temp) > 2){
   stroke(224, 38, 41);
     line(64, 64, endx, endy);
     line(65, 64, endx, endy);
     line(63, 64, endx, endy);
     line(64, 65, endx, endy);
     line(64, 63, endx, endy);
   stroke(0,0,0);
     line(64, 63, o_endx, o_endy);
     line(64, 65, o_endx, o_endy);
     line(63, 64, o_endx, o_endy);
     line(65, 64, o_endx, o_endy);
     line(64, 64, o_endx, o_endy);
   }
   o_endx = endx;
   o_endy = endy;
   //for debugging --v
   /*char char_xy[7];
   fmtDouble(endx, 2, char_xy, 7);
   lcd_puts(char_xy, 10, 10, gaugeRed, black);
   fmtDouble(endy, 2, char_xy, 7);
   lcd_puts(char_xy, 20, 20, gaugeRed, black);*/
   //--^
   //print deg F
   //do conversion from int to string with decimal places
   char char_oil_temp[7];
   fmtDouble(oil_temp, 2, char_oil_temp, 7);
   lcd_puts(char_oil_temp, 80, 72, gaugeRed, mblack);
   //delay(500); //for testing
   //bmp_draw("oilgaug",0,0);
  }
  while (touch_get_cursor(&m_point)){} //debounce
  boost_gauge(); //next gauge
}