/*
 GerberConversion
 Copyright (C) 2010 Martin Štrympl
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public
 License as published by the Free Software Foundation; either
 version 3.0 of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 General Public License for more details.
 
 You should have received a copy of the GNU General Public
 License along with this program.
 
 Martin Štrympl
 xstrym00@stud.feec.vutbr.cz
 */
 
#include "Code.h"

#include "Number.h"

Mac_Fun_Gerber_Gerber_Code(Code_XY)
{
  char ch_xy;
  //char *t_begin;
  
  struct sNumber_Number s_number;
  
  ch_xy = **pt_text;
  (*pt_text)++;
  
  //t_begin = *pt_text;
  if (!LoadNumber(&s_number, pt_text, ps_actual, ch_xy))
  {
    (*pt_text)--; // ??
    printf("Number reading failed for X coordinate.\n");
    return 1;
  }
  (*pt_text)--;
  
  //#warning Convert by sets with MO
  
  if (ch_xy=='X')
  {
    
    //ps_actual->s_xy.s_old.ld_x=ps_actual->s_xy.s_new.ld_x;
    ps_actual->s_xy.s_new.ld_x=s_number.ld_number;
    if (ps_actual->s_fs.b_AI==false) ps_actual->s_xy.s_new.ld_x+=ps_actual->s_xy.s_old.ld_x;
    
    if (ps_actual->s_sets.i4_debug>2) printf("Axis X in new point set with number %6.6f to %6.6f.\n", (double)ps_actual->s_xy.s_new.ld_x, (double)s_number.ld_number); 
  }
  else
  {
    //ps_actual->s_xy.s_old.ld_y=ps_actual->s_xy.s_new.ld_y;
    ps_actual->s_xy.s_new.ld_y=s_number.ld_number;
    if (ps_actual->s_fs.b_AI==false) ps_actual->s_xy.s_new.ld_y+=ps_actual->s_xy.s_old.ld_y;
    
    if (ps_actual->s_sets.i4_debug>2) printf("Axis Y in new point set with number %6.6f to %6.6f.\n", (double)ps_actual->s_xy.s_new.ld_y, (double)s_number.ld_number); 
  }
  
  return 0;
}
Mac_Fun_Gerber_Gerber_Code(Code_IJ)
{
  char ch_xy;
  //char *t_begin;
  
  struct sNumber_Number s_number;
  
  ch_xy = **pt_text;
  (*pt_text)++;
  
  if (ch_xy=='I') ch_xy='X';
  else ch_xy='Y';
  //t_begin = *pt_text;
  if (!LoadNumber(&s_number, pt_text, ps_actual, ch_xy))
  {
    (*pt_text)--; // ??
    printf("Number reading failed for X coordinate.\n");
    return 1;
  }
  (*pt_text)--;
  
  //#warning Convert by sets with MO
  
  if (ch_xy=='X')
  {
    
    //ps_actual->s_xy.s_old.ld_x=ps_actual->s_xy.s_new.ld_x;
    ps_actual->s_xy.s_offset.ld_x=s_number.ld_number;
    
    if (ps_actual->s_sets.i4_debug>2) printf("Axis X offset in new point set with number %6.6f to %6.6f.\n", (double)ps_actual->s_xy.s_offset.ld_x, (double)s_number.ld_number); 
  }
  else
  {
    //ps_actual->s_xy.s_old.ld_y=ps_actual->s_xy.s_new.ld_y;
    ps_actual->s_xy.s_offset.ld_y=s_number.ld_number;
    
    if (ps_actual->s_sets.i4_debug>2) printf("Axis Y offset in new point set with number %6.6f to %6.6f.\n", (double)ps_actual->s_xy.s_offset.ld_y, (double)s_number.ld_number); 
  }
  
  return 0;
}
Mac_Fun_Gerber_Gerber_Code(Code_D)
{
  char ch_xy;
  struct sNumber_Number s_number;
  
  //struct sGerber_Point s_A, s_B;
  
  // offset aplicate to point and zeros copied to new offset value
  /*ps_actual->s_xy.s_new.ld_x+=ps_actual->s_xy.s_offset.ld_x;
  ps_actual->s_xy.s_new.ld_y+=ps_actual->s_xy.s_offset.ld_y;
  ps_actual->s_xy.s_offset.ld_x=0.0L;
  ps_actual->s_xy.s_offset.ld_y=0.0L;*/
  // offset aplacate in code
  
  ch_xy = **pt_text;
  (*pt_text)++;
  
  //t_begin = *pt_text;
  if (!LoadNumber(&s_number, pt_text, ps_actual, ch_xy))
  {
    (*pt_text)--; // ??
    printf("Number reading failed for D code.\n");
    return 1;
  }
  (*pt_text)--;
  
  if (s_number.i4_integer<10)
  {
    int s4_return;
    if (s_number.i4_integer>3)
    {
      printf("Unknown D code number %i.\n", s_number.i4_integer);
      return -1;
    }
    switch (s_number.i4_integer)
    {
        case 1:
          // draw with G code
          if (ps_actual->s_sets.i4_debug>2) printf("Draw from [%6.6f,%6.6f] to [%6.6f,%6.6f].\n",
                                                   (double)ps_actual->s_xy.s_old.ld_x, (double)ps_actual->s_xy.s_old.ld_y,
                                                   (double)ps_actual->s_xy.s_new.ld_x, (double)ps_actual->s_xy.s_new.ld_y);
          
          /*
          if (!RealPoint(ps_actual, &s_A, &ps_actual->s_xy.s_old))
          {
            printf("Transform old point from axis X and Y to axis A and B failed.\n");
            return -1;
          }
          if (!RealPoint(ps_actual, &s_B, &ps_actual->s_xy.s_new))
          {
            printf("Transform new point from axis X and Y to axis A and B failed.\n");
            return -1;
          }*/
          //s_A=*ps_actual->s_xy.s_old;
          //s_B=*ps_actual->s_xy.s_new;
          // Must you check any settings in future?
          /*if (ps_actual->s_sets.i4_debug>2) printf("Draw transform line from [%6.6f,%6.6f] to [%6.6f,%6.6f].\n",
                                                   (double)s_A.ld_x, (double)s_A.ld_y, (double)s_B.ld_x, (double)s_B.ld_y);
          
          Gerber_Gerber_LineSegment(ps_gerber, &s_A, &s_B, false);*/
          
          s4_return=ps_actual->f_gcode(ps_gerber, ps_actual);
          
          ps_actual->s_xy.s_old=ps_actual->s_xy.s_new;
          ps_actual->s_xy.s_offset.ld_x=0;
          ps_actual->s_xy.s_offset.ld_y=0;
          return s4_return;
        case 2:
          // no draw enything
          if (ps_actual->s_sets.i4_debug>2) printf("Move new point to old point.\n");
          ps_actual->s_xy.s_old=ps_actual->s_xy.s_new;
          ps_actual->s_xy.s_offset.ld_x=0;
          ps_actual->s_xy.s_offset.ld_y=0;
          return 0;
        case 3:
          if (ps_actual->u4_selectedDcode==0)
          {
            printf("Move new point to old point.\n");
            return -1;
          }
          if (ps_actual->s_dcodes.as_codes[ps_actual->u4_selectedDcode].f_dcode==NULL)
          {
            printf("D code number %i is not defined.\n", s_number.i4_integer);
            return -1;
          }
          
          if (ps_actual->s_sets.i4_debug>2) printf("Flash the current aparature of D code number %i with points [%6.6f,%6.6f] and [%6.6f,%6.6f].\n", ps_actual->u4_selectedDcode,
                                                   (double)ps_actual->s_xy.s_old.ld_x, (double)ps_actual->s_xy.s_old.ld_y,
                                                   (double)ps_actual->s_xy.s_new.ld_x, (double)ps_actual->s_xy.s_new.ld_y);
          
          s4_return=ps_actual->s_dcodes.as_codes[ps_actual->u4_selectedDcode].f_dcode(ps_gerber, ps_actual, &ps_actual->s_dcodes.as_codes[ps_actual->u4_selectedDcode].u_data);
          
          ps_actual->s_xy.s_old=ps_actual->s_xy.s_new;
          ps_actual->s_xy.s_offset.ld_x=0;
          ps_actual->s_xy.s_offset.ld_y=0;
          
          return s4_return;
        default:
          printf("Unsoported D code number %i.\n", s_number.i4_integer);
          return -1;
    }
  }
  else
  {
    if ((s_number.i4_integer<10)||(s_number.i4_integer>999))
    {
      printf("D code number %i is bad.\n", s_number.i4_integer);
      return -1;
    }
    if (ps_actual->s_dcodes.as_codes[s_number.i4_integer].f_dcode!=NULL)
    {
      ps_actual->u4_selectedDcode=s_number.i4_integer;
      //return ps_actual->s_dcodes.as_codes[s_number.i4_integer].f_dcode(ps_gerber, ps_actual, &ps_actual->s_dcodes.as_codes[s_number.i4_integer].u_data, pt_text);
      return 0;
    }
    printf("D code number %i is not defined.\n", s_number.i4_integer);
    return -1;
  }
  
  return 0;
}
Mac_Fun_Gerber_Gerber_Code(Code_G)
{
  char ch_xy;
  struct sNumber_Number s_number;
  
  // offset aplicate to point and zeros copied to new offset value
  ps_actual->s_xy.s_new.ld_x+=ps_actual->s_xy.s_offset.ld_x;
  ps_actual->s_xy.s_new.ld_y+=ps_actual->s_xy.s_offset.ld_y;
  ps_actual->s_xy.s_offset.ld_x=0.0L;
  ps_actual->s_xy.s_offset.ld_y=0.0L;
  
  ch_xy = **pt_text;
  (*pt_text)++;
  
  //t_begin = *pt_text;
  if (!LoadNumber(&s_number, pt_text, ps_actual, ch_xy))
  {
    (*pt_text)--; // ??
    printf("Number reading failed for G code.\n");
    return 1;
  }
  (*pt_text)--;
  
  switch (s_number.i4_integer)
  {
    case 1:
      if (ps_actual->s_sets.i4_debug>1) printf("Activate linear interpolation by G code 1.\n");
      ps_actual->f_gcode=Gcode_01;
      return 0;
    case 2:
      if (ps_actual->s_sets.i4_debug>1) printf("Activate clockwise circular interpolation by G code 2.\n");
      ps_actual->f_gcode=Gcode_02;
      return 0;
    case 3:
      if (ps_actual->s_sets.i4_debug>1) printf("Activate counter clockwise circular interpolation by G code 3.\n");
      ps_actual->f_gcode=Gcode_03;
      return 0;
    case 4: // G04, comment
      if (ps_actual->s_sets.i4_debug>1) printf("Ignoring commented block by G code 4.\n");
      while (**pt_text)
      {
        if ((**pt_text=='*')||(**pt_text<0x20)) break;
        (*pt_text)++;
      }
      return 0;
    case 36:
    case 37:
      if (ps_actual->s_sets.i4_debug>1) printf("Ignoring G code %i. Fill settings is not meaning for cutting.\n", s_number.i4_integer);
      return 0;
    case 54:
      if (ps_actual->s_sets.i4_debug>1) printf("Ignoring historical G code 54.\n");
      return 0;
    case 74:
      if (ps_actual->s_sets.i4_debug>1) printf("Activate single quadrant mode by G code 74.\n");
      return 0;
    case 75:
      if (ps_actual->s_sets.i4_debug>1) printf("Activate multi quadrant mode by G code 75.\n");
      return 0;
    case 90:
      if (ps_actual->s_sets.i4_debug>1) printf("Activate absolute format by G code 90.\n");
      ps_actual->s_fs.b_AI=true;
      return 0;
    case 91:
      if (ps_actual->s_sets.i4_debug>1) printf("Activate incremental format by G code 90.\n");
      ps_actual->s_fs.b_AI=false;
      return 0;
    default: 
      printf("G code number %i is not supported.\n", s_number.i4_integer);
      return -1; // unknown G code
  }
  return 0;
}
Mac_Fun_Gerber_Gerber_Code(Code_M)
{
  char ch_xy;
  struct sNumber_Number s_number;
  
  // offset aplicate to point and zeros copied to new offset value
  ps_actual->s_xy.s_new.ld_x+=ps_actual->s_xy.s_offset.ld_x;
  ps_actual->s_xy.s_new.ld_y+=ps_actual->s_xy.s_offset.ld_y;
  ps_actual->s_xy.s_offset.ld_x=0.0L;
  ps_actual->s_xy.s_offset.ld_y=0.0L;
  
  ch_xy = **pt_text;
  (*pt_text)++;
  
  //t_begin = *pt_text;
  if (!LoadNumber(&s_number, pt_text, ps_actual, ch_xy))
  {
    (*pt_text)--; // ??
    printf("Number reading failed for M code.\n");
    return 1;
  }
  (*pt_text)--;
  
  if (s_number.i4_integer==2)
  {
    return 100;
  }
  else
  {
    if (ps_actual->s_sets.i4_debug>1) printf("Ignoring old M code.\n");
  }
  
  return 0;
}

bool Gerber_Gerber_AutoCodeRegister(struct sGerber_Gerber *ps_gerber)
{
  bool b_how = true;
  
  b_how &= Gerber_Gerber_RegisterCode(ps_gerber, "X", Code_XY);
  b_how &= Gerber_Gerber_RegisterCode(ps_gerber, "Y", Code_XY);
  b_how &= Gerber_Gerber_RegisterCode(ps_gerber, "I", Code_IJ);
  b_how &= Gerber_Gerber_RegisterCode(ps_gerber, "J", Code_IJ);
  
  b_how &= Gerber_Gerber_RegisterCode(ps_gerber, "D", Code_D);
  b_how &= Gerber_Gerber_RegisterCode(ps_gerber, "G", Code_G);
  b_how &= Gerber_Gerber_RegisterCode(ps_gerber, "M", Code_M);
  return b_how;
}
