/*
 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
 */

/*
 *  Settings.c
 *  GerberConversion
 *
 *  Created by Martin Štrympl on 11/2/10.
 *  Copyright 2010 School. All rights reserved.
 *
 */
 
#include "Set.h"

#include "Number.h"

#include "Dcodes.h"

Mac_Fun_Gerber_Gerber_Settings(Set_ADD)
{
  struct sNumber_Number s_number;
  uint32_t u4_Dcode;
  
  char *t_testMacro;
  
  (*pt_text)+=3;
  if (!LoadNumber(&s_number, pt_text, ps_actual, 'i'))
  {
    (*pt_text)--; // ??
    printf("Number reading failed for D-code number.\n");
    return 1;
  }
  u4_Dcode=s_number.i4_integer;
  
  if ((u4_Dcode<10)||(u4_Dcode>999))
  {
    printf("ADD set can not set D-code number %u.\n", u4_Dcode);
    return -1;
  }
  
  t_testMacro=*pt_text;
  
  for (;*t_testMacro!=0;t_testMacro++)
  {
    if (!(((*t_testMacro>='a')&&(*t_testMacro>='z'))||((*t_testMacro>='A')&&(*t_testMacro>='Z')))) break;
  }
  if (*t_testMacro=='*')
  {
    printf("Macro in ADD set is not supported.\n");
    return -1;
  }
  t_testMacro++;
  if (*t_testMacro!=',')
  {
    printf("Bad data format in ADD set. Expected char is ',', but char '%c'(0x%X) detected.\n", *t_testMacro, *t_testMacro);
    return -2;
  }
  
  switch (**pt_text)
  {
    case 'C': // Circle
      *pt_text=t_testMacro;
      
      if (ps_actual->s_dcodes.as_codes[u4_Dcode].f_dcode!=NULL)
      {
        printf("ADD set changing exists D-code number %u.\n", u4_Dcode);
      }
      ps_actual->s_dcodes.as_codes[u4_Dcode].f_dcode=NULL;
      
      (*pt_text)++;
      if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
      {
        (*pt_text)--; // ??
        printf("Number reading failed for Circle dimeter.\n");
        return 1;
      }
      
      ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_circle.ld_diameter=RealDimension(ps_actual, s_number.ld_number);
      
      ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_circle.ld_xhole=0.000000000L;
      ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_circle.ld_yhole=0.000000000L;
      
      if (**pt_text=='X')
      {
        (*pt_text)++;
        if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
        {
          (*pt_text)--; // ??
          printf("Number reading failed for Circle X axis hole dimension.\n");
          return 1;
        }
        ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_circle.ld_xhole=RealDimension(ps_actual, s_number.ld_number);
      }
      if (**pt_text=='X')
      {
        (*pt_text)++;
        if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
        {
          (*pt_text)--; // ??
          printf("Number reading failed for Circle Y axis hole dimension.\n");
          return 1;
        }
        ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_circle.ld_yhole=RealDimension(ps_actual, s_number.ld_number);
      }
      
      (*pt_text)--;
      
      ps_actual->s_dcodes.as_codes[u4_Dcode].f_dcode=Dcode_Circle;
      
      printf("ADD set set D-code number %u to Circle with outside dimeter %6.6f.\n", u4_Dcode,
             (double)ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_circle.ld_diameter);
      break;
    case 'R': // Rectange
      *pt_text=t_testMacro;
      
      if (ps_actual->s_dcodes.as_codes[u4_Dcode].f_dcode!=NULL)
      {
        printf("ADD set changing exists D-code number %u.\n", u4_Dcode);
      }
      ps_actual->s_dcodes.as_codes[u4_Dcode].f_dcode=NULL;
      
      (*pt_text)++;
      if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
      {
        (*pt_text)--; // ??
        printf("Number reading failed for Rectange X axis dimenzion.\n");
        return 1;
      }
      
      ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_rectange.ld_x=s_number.ld_number;
      
      (*pt_text)++;
      if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
      {
        (*pt_text)--; // ??
        printf("Number reading failed for Rectange Y axis dimenzion.\n");
        return 1;
      }
      
      ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_rectange.ld_y=s_number.ld_number;
      
      ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_rectange.ld_xhole=0.0;
      ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_rectange.ld_yhole=0.0;
      
      if (**pt_text=='X')
      {
        (*pt_text)++;
        if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
        {
          (*pt_text)--; // ??
          printf("Number reading failed for Rectange X axis hole dimension.\n");
          return 1;
        }
        ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_circle.ld_xhole=s_number.ld_number;
      }
      if (**pt_text=='X')
      {
        (*pt_text)++;
        if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
        {
          (*pt_text)--; // ??
          printf("Number reading failed for Rectange Y axis hole dimension.\n");
          return 1;
        }
        ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_circle.ld_yhole=s_number.ld_number;
      }
      
      (*pt_text)--;
      
      ps_actual->s_dcodes.as_codes[u4_Dcode].f_dcode=Dcode_Circle;
      
      printf("ADD set set D-code number %u to Rectange with X axis dimension %6.6f and Y axis dimension %6.6f.\n", u4_Dcode,
             (double)ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_circle.ld_xhole,
             (double)ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_circle.ld_yhole);
      break;
    case 'O': // Oround(Oval)
      *pt_text=t_testMacro;
      
      if (ps_actual->s_dcodes.as_codes[u4_Dcode].f_dcode!=NULL)
      {
        printf("ADD set changing exists D-code number %u.\n", u4_Dcode);
      }
      ps_actual->s_dcodes.as_codes[u4_Dcode].f_dcode=NULL;
      
      (*pt_text)++;
      if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
      {
        (*pt_text)--; // ??
        printf("Number reading failed for Oround X axis dimension.\n");
        return 1;
      }
      
      ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_oround.ld_x=RealDimension(ps_actual, s_number.ld_number);
      
      if (**pt_text!='X')
      {
        (*pt_text)--; // ??
        printf("Oround Y axis dimension is missing.\n");
        return 1;
      }
      
      (*pt_text)++;
      if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
      {
        (*pt_text)--; // ??
        printf("Number reading failed for Oround X axis dimension.\n");
        return 1;
      }
      
      ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_oround.ld_y=RealDimension(ps_actual, s_number.ld_number);
      
      ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_oround.ld_xhole=0.000000000L;
      ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_oround.ld_yhole=0.000000000L;
      
      if (**pt_text=='X')
      {
        (*pt_text)++;
        if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
        {
          (*pt_text)--; // ??
          printf("Number reading failed for Oround X axis hole dimension.\n");
          return 1;
        }
        ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_oround.ld_xhole=RealDimension(ps_actual, s_number.ld_number);
      }
      if (**pt_text=='X')
      {
        (*pt_text)++;
        if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
        {
          (*pt_text)--; // ??
          printf("Number reading failed for Oround Y axis hole dimension.\n");
          return 1;
        }
        ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_oround.ld_yhole=RealDimension(ps_actual, s_number.ld_number);
      }
      
      (*pt_text)--;
      
      ps_actual->s_dcodes.as_codes[u4_Dcode].f_dcode=Dcode_Circle;
      
      printf("ADD set set D-code number %u to Oround with outside dimeter %6.6f in X axis and %6.6f in Y axis.\n", u4_Dcode,
             (double)ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_oround.ld_x,
             (double)ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_oround.ld_y);
      break;
    case 'P': // Regular polynom
      *pt_text=t_testMacro;
      
      if (ps_actual->s_dcodes.as_codes[u4_Dcode].f_dcode!=NULL)
      {
        printf("ADD set changing exists D-code number %u.\n", u4_Dcode);
      }
      ps_actual->s_dcodes.as_codes[u4_Dcode].f_dcode=NULL;
      
      (*pt_text)++;
      if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
      {
        (*pt_text)--; // ??
        printf("Number reading failed for Regular polynom outside dimension.\n");
        return 1;
      }
      
      ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_regular.ld_diameter=RealDimension(ps_actual, s_number.ld_number);
      
      if (**pt_text!='X')
      {
        (*pt_text)--; // ??
        printf("Regular polynom number of sides is missing.\n");
        return 1;
      }
      
      (*pt_text)++;
      if (!LoadNumber(&s_number, pt_text, ps_actual, 'i'))
      {
        (*pt_text)--; // ??
        printf("Number reading failed for Regular polynom X axis dimension.\n");
        return 1;
      }
      
      ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_regular.u4_sides=s_number.i4_integer;
      
      ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_regular.ld_agleStart=0.000000000L;
      ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_regular.ld_xhole=0.000000000L;
      ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_regular.ld_yhole=0.000000000L;
      
      if (**pt_text=='X')
      {
        (*pt_text)++;
        if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
        {
          (*pt_text)--; // ??
          printf("Number reading failed for Regular polynom degrees of rotation.\n");
          return 1;
        }
        ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_regular.ld_agleStart=RealDimension(ps_actual, s_number.ld_number);
      }
      if (**pt_text=='X')
      {
        (*pt_text)++;
        if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
        {
          (*pt_text)--; // ??
          printf("Number reading failed for Regular polynom X axis hole dimension.\n");
          return 1;
        }
        ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_regular.ld_xhole=RealDimension(ps_actual, s_number.ld_number);
      }
      if (**pt_text=='X')
      {
        (*pt_text)++;
        if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
        {
          (*pt_text)--; // ??
          printf("Number reading failed for Regular polynom Y axis hole dimension.\n");
          return 1;
        }
        ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_regular.ld_yhole=RealDimension(ps_actual, s_number.ld_number);
      }
      
      (*pt_text)--;
      
      ps_actual->s_dcodes.as_codes[u4_Dcode].f_dcode=Dcode_Circle;
      
      printf("ADD set set D-code number %u to Regular polynom with outside dimeter %6.6f.\n", u4_Dcode,
             (double)ps_actual->s_dcodes.as_codes[u4_Dcode].u_data.s_regular.ld_diameter);
      break;
    default:
      printf("ADD set do not know aperture type '%c'.\n", **pt_text);
      return -1;
  }
  
  //printf("ADD set set D-code number %u to %s.\n", u4_Dcode);
  
  return 0;
}

Mac_Fun_Gerber_Gerber_Settings(Set_AS)
{
  (*pt_text)+=2;
  if ((**pt_text)!='A')
  {
    printf("Missing AS sets.\n");
    return -1;
  }
  (*pt_text)++;
  
  if ((**pt_text)=='X') ps_actual->s_as.b_A=true;
  else if ((**pt_text)=='Y') ps_actual->s_as.b_A=false;
  else
  {
    printf("Unknown AS sets.\n");
    return -1;
  }
  
  (*pt_text)++;
  
  if ((**pt_text)!='B')
  {
    printf("Missing AS sets.\n");
    return -1;
  }
  (*pt_text)++;
  
  if ((**pt_text)=='X') ps_actual->s_as.b_B=true;
  else if ((**pt_text)=='Y') ps_actual->s_as.b_B=false;
  else
  {
    printf("Unknown AS sets.\n");
    return -1;
  }
  
  printf("AS set to A=%c and B=%c.\n", (ps_actual->s_as.b_A)?('X'):('Y'), (ps_actual->s_as.b_B)?('X'):('Y'));
  
  return 0;
}
Mac_Fun_Gerber_Gerber_Settings(Set_FS)
{
  (*pt_text)+=2;
  
  if ((**pt_text)=='L') ps_actual->s_fs.b_LT=true;
  else if ((**pt_text)=='T') ps_actual->s_fs.b_LT=false;
  else
  {
    printf("Unknown FS sets.\n");
    return -1;
  }
  
  (*pt_text)++;
  
  if ((**pt_text)=='A') ps_actual->s_fs.b_AI=true;
  else if ((**pt_text)=='I') ps_actual->s_fs.b_AI=false;
  else
  {
    printf("Unknown FS sets.\n");
    return -1;
  }
  
  (*pt_text)++;
  
  if ((**pt_text)=='N')
  {
    (*pt_text)++;
    if (((**pt_text)>='0')&&((**pt_text)<='9'))
    {
      ps_actual->s_fs.u1_N=((**pt_text)-'0');
      (*pt_text)++;
    }
    else
    {
      printf("Unknown FS sets.\n");
      return -1;
    }
  }
  if ((**pt_text)=='G')
  {
    (*pt_text)++;
    if (((**pt_text)>='0')&&((**pt_text)<='9'))
    {
      ps_actual->s_fs.u1_G=((**pt_text)-'0');
      (*pt_text)++;
    }
    else
    {
      printf("Unknown FS sets.\n");
      return -1;
    }
  }
  
  if ((**pt_text)=='X')
  {
    (*pt_text)++;
    if (((**pt_text)>='0')&&((**pt_text)<='9'))
    {
      ps_actual->s_fs.u1_X_integer=((**pt_text)-'0');
      (*pt_text)++;
    }
    else
    {
      printf("Unknown FS sets.\n");
      return -1;
    }
    if (((**pt_text)>='0')&&((**pt_text)<='9'))
    {
      ps_actual->s_fs.u1_X_decimal=((**pt_text)-'0');
      (*pt_text)++;
    }
    else
    {
      printf("Unknown FS sets.\n");
      return -1;
    }
  }
  else
  {
    printf("Missing FS sets.\n");
    return -1;
  }
  if ((**pt_text)=='Y')
  {
    (*pt_text)++;
    if (((**pt_text)>='0')&&((**pt_text)<='9'))
    {
      ps_actual->s_fs.u1_Y_integer=((**pt_text)-'0');
      (*pt_text)++;
    }
    else
    {
      printf("Unknown FS sets.\n");
      return -1;
    }
    if (((**pt_text)>='0')&&((**pt_text)<='9'))
    {
      ps_actual->s_fs.u1_Y_decimal=((**pt_text)-'0');
      (*pt_text)++;
    }
    else
    {
      printf("Unknown FS sets.\n");
      return -1;
    }
  }
  else
  {
    printf("Missing FS sets.\n");
    return -1;
  }
  
  if ((**pt_text)=='D')
  {
    (*pt_text)++;
    if (((**pt_text)>='0')&&((**pt_text)<='9'))
    {
      ps_actual->s_fs.u1_D=((**pt_text)-'0');
      (*pt_text)++;
    }
    else
    {
      printf("Unknown FS sets.\n");
      return -1;
    }
  }
  if ((**pt_text)=='M')
  {
    (*pt_text)++;
    if (((**pt_text)>='0')&&((**pt_text)<='9'))
    {
      ps_actual->s_fs.u1_M=((**pt_text)-'0');
      (*pt_text)++;
    }
    else
    {
      printf("Unknown FS sets.\n");
      return -1;
    }
  }
  (*pt_text)--;
  
  printf("FS set to %s zeros with %s coordinate and X%u.%u Y%u.%u N%u G%u D%u M%u.\n",
         (ps_actual->s_fs.b_LT)?("leading"):("trailing"), (ps_actual->s_fs.b_AI)?("absolute"):("incremental"), 
         (uint32_t)ps_actual->s_fs.u1_X_integer, (uint32_t)ps_actual->s_fs.u1_X_decimal,
         (uint32_t)ps_actual->s_fs.u1_Y_integer, (uint32_t)ps_actual->s_fs.u1_Y_decimal,
         (uint32_t)ps_actual->s_fs.u1_N, (uint32_t)ps_actual->s_fs.u1_G,
         (uint32_t)ps_actual->s_fs.u1_D, (uint32_t)ps_actual->s_fs.u1_M);
    
  return 0;
}

Mac_Fun_Gerber_Gerber_Settings(Set_MI)
{
  (*pt_text)+=2;
  if ((**pt_text)=='A')
  {
    (*pt_text)++;
    if ((**pt_text)=='0') ps_actual->s_mi.b_A=false;
    else if ((**pt_text)=='1') ps_actual->s_mi.b_A=true;
    else
    {
      printf("Unknown MI sets.\n");
      return -1;
    }
    (*pt_text)++;
  }
  
  if ((**pt_text)=='B')
  {
    (*pt_text)++;
    if ((**pt_text)=='0') ps_actual->s_mi.b_B=false;
    else if ((**pt_text)=='1') ps_actual->s_mi.b_B=true;
    else
    {
      printf("Unknown MI sets.\n");
      return -1;
    }
    (*pt_text)++;
  }
  
  (*pt_text)--;
  
  printf("MI set to A=%s and B=%s.\n", (ps_actual->s_mi.b_A)?("-A"):("A"), (ps_actual->s_mi.b_B)?("-B"):("B"));
  
  return 0;
}
Mac_Fun_Gerber_Gerber_Settings(Set_MO)
{
  (*pt_text)+=2;
  if (((*pt_text)[0]=='I')&&((*pt_text)[1]=='N')) ps_actual->s_mo.b_inch=true;
  else if (((*pt_text)[0]=='M')&&((*pt_text)[1]=='M')) ps_actual->s_mo.b_inch=false;
  else
  {
    printf("Unknown MO sets.\n");
    return -1;
  }
  (*pt_text)++;
  
  printf("MO set to %s.\n", (ps_actual->s_mo.b_inch)?("inch"):("millimeters"));
  
  return 0;
}

Mac_Fun_Gerber_Gerber_Settings(Set_OF)
{
  struct sNumber_Number s_number;
  
  (*pt_text)+=2;
  if ((**pt_text)=='A')
  {
    (*pt_text)++;
    if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
    {
      (*pt_text)--; // ??
      printf("Number reading failed for A offset.\n");
      return 1;
    }
    
    if ((s_number.u1_integer>5)||(s_number.u1_decimal>5))
    {
      (*pt_text)--;
      printf("Bad offset A range.\n");
      return -1;
    }
    
    ps_actual->s_of.ld_A=s_number.ld_number;
  }
  
  if ((**pt_text)=='B')
  {
    (*pt_text)++;
    if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
    {
      (*pt_text)--; // ??
      printf("Number reading failed for A offset.\n");
      return 1;
    }
    
    if ((s_number.u1_integer>5)||(s_number.u1_decimal>5))
    {
      (*pt_text)--;
      printf("Bad offset A range.\n");
      return -1;
    }
    
    ps_actual->s_of.ld_B=s_number.ld_number;
  }
  
  (*pt_text)--;
  
  printf("OF set to A=%5.5f and B=%5.5f.\n", (double)ps_actual->s_of.ld_A, (double)ps_actual->s_of.ld_B);
  
  return 0;
}

Mac_Fun_Gerber_Gerber_Settings(Set_SF)
{
  struct sNumber_Number s_number;
  
  (*pt_text)+=2;
  if ((**pt_text)=='A')
  {
    (*pt_text)++;
    if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
    {
      (*pt_text)--; // ??
      printf("Number reading failed for A scale factor.\n");
      return 1;
    }
    
    if ((s_number.u1_integer>3)||(s_number.u1_decimal>5))
    {
      (*pt_text)--;
      printf("Bad scale A range.\n");
      return -1;
    }
    
    ps_actual->s_sf.ld_A=s_number.ld_number;
  }
  
  if ((**pt_text)=='B')
  {
    (*pt_text)++;
    if (!LoadNumber(&s_number, pt_text, ps_actual, 'd'))
    {
      (*pt_text)--; // ??
      printf("Number reading failed for B scale factor.\n");
      return 1;
    }
    
    if ((s_number.u1_integer>3)||(s_number.u1_decimal>5))
    {
      (*pt_text)--;
      printf("Bad scale B range.\n");
      return -1;
    }
    
    ps_actual->s_sf.ld_B=s_number.ld_number;
  }
  
  (*pt_text)--;
  
  printf("SF set to A=%3.5f and B=%3.5f.\n", (double)ps_actual->s_sf.ld_A, (double)ps_actual->s_sf.ld_B);
  
  return 0;
}

bool Gerber_Gerber_AutoSetsRegister(struct sGerber_Gerber *ps_gerber)
{
  bool b_how = true;
  
  //b_how &= Gerber_Gerber_RegisterSettings(ps_gerber, "", Set_);
  
  b_how &= Gerber_Gerber_RegisterSettings(ps_gerber, "ADD", Set_ADD);
  
  b_how &= Gerber_Gerber_RegisterSettings(ps_gerber, "AS", Set_AS);
  
  b_how &= Gerber_Gerber_RegisterSettings(ps_gerber, "FS", Set_FS);
  
  b_how &= Gerber_Gerber_RegisterSettings(ps_gerber, "MI", Set_MI);
  b_how &= Gerber_Gerber_RegisterSettings(ps_gerber, "MO", Set_MO);
  
  b_how &= Gerber_Gerber_RegisterSettings(ps_gerber, "OF", Set_OF);
  
  b_how &= Gerber_Gerber_RegisterSettings(ps_gerber, "SF", Set_SF);
  
  return b_how;
}
