/*
 AurelALS300data
 Copyright (C) 2010 Martin Štrympl

 This library 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 library 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 library.

 Martin Štrympl
 xstrym00@stud.feec.vutbr.cz
 */

/*
 *  main.c
 *  AurelALS300data
 *
 *  Created by Martin Štrympl on 11/10/10.
 *  Copyright 2010 School. All rights reserved.
 *
 */

#include "main.h"

#include "data.h"

#define MY_PI (3.141592653589793L)

struct sData s_data;

Mac_Fun_Gerber_Module_Start(Start)
{
  uint32_t u4_n;

  printf("Module AurelALS300data: Version 1.6\n");
  printf("Module AurelALS300data: Programed by Martin Stympl. Mail: mail: xstrym00@stud.feec.vutbr.cz\n");
  printf("Module AurelALS300data: Compiled time: %s %s\n", __DATE__, __TIME__);

  s_data.t_data=NULL;
  s_data.t_command=NULL;

  s_data.as_elements=NULL;
  s_data.u4_elements=0;

  // header default
  s_data.s_header.u4_lasReferenceX=s_data.s_header.u4_lasReferenceY=100.0;
  s_data.s_header.i4_masterRefXProbeA=s_data.s_header.i4_masterRefYProbeA=0;
  s_data.s_header.i4_masterRefXProbeB=s_data.s_header.i4_masterRefYProbeB=0;

  s_data.s_header.do_current=15.0;
  s_data.s_header.do_freq=1.0;
  s_data.s_header.do_speed=0.5;

  s_data.s_header.u4_cuts=10;

  s_data.s_header.b_transformate=false;
  s_data.s_header.b_transToZero=false;

  s_data.i4_width=50*800;
  s_data.i4_height=50*800;

  // arguments

  for (u4_n=0;u4_n<u4_args;u4_n++)
  {
    if (strcmp(at_args[u4_n],"--data")==0)
    {
      u4_n++;
      if (u4_n<u4_args)
      {
        // output filename
        uint32_t u4_len;

        u4_len=strlen(at_args[u4_n]+1)+1;

        if (s_data.t_data) free(s_data.t_data);
        s_data.t_data = malloc(u4_len);

        if (s_data.t_data)
        {
          memcpy(s_data.t_data, at_args[u4_n]+1, u4_len);
          printf("Module AurelALS300data: Output data file name set to '%s'\n", at_args[u4_n]+1);
        }
        else
        {
          printf("Module AurelALS300data: Copy output data file name failed.\n");
          return -1;
        }
      }
      else
      {
        printf("Module AurelALS300data: Missing modificator '%s' value.\n", at_args[u4_n-1]);
        return -1;
      }
    }
    else if (strcmp(at_args[u4_n],"--commands")==0)
    {
      u4_n++;
      if (u4_n<u4_args)
      {
        // output filename
        uint32_t u4_len;

        u4_len=strlen(at_args[u4_n]+1)+1;

        if (s_data.t_command) free(s_data.t_command);
        s_data.t_command = malloc(u4_len);

        if (s_data.t_command)
        {
          memcpy(s_data.t_command, at_args[u4_n]+1, u4_len);
          printf("Module AurelALS300data: Output commands file name set to '%s'\n", at_args[u4_n]+1);
        }
        else
        {
          printf("Module AurelALS300data: Copy output commands file name failed.\n");
          return -1;
        }
      }
      else
      {
        printf("Module AurelALS300data: Missing modificator '%s' value.\n", at_args[u4_n-1]);
        return -1;
      }
    }
    else if (strcmp(at_args[u4_n],"--laserReferenceX")==0)
    {
      u4_n++;
      if (u4_n<u4_args)
      {
        long double ld_read;
        ld_read=atof(at_args[u4_n]+1);
        if (ld_read<0.0L)
        {
          printf("Module AurelALS300data: Bad laser reference X value %6.2f. Value is less than zero.\n", (double)ld_read);
          return -1;
        }
        else
        {
          s_data.s_header.u4_lasReferenceX=floor(ld_read*800.0L+0.5L)+0.1L;
          printf("Module AurelALS300data: Laser reference X set to %6.2f\n", (double)ld_read);
        }
      }
      else
      {
        printf("Module AurelALS300data: Missing modificator '%s' value.\n", at_args[u4_n-1]);
        return -1;
      }
    }
    else if (strcmp(at_args[u4_n],"--laserReferenceY")==0)
    {
      u4_n++;
      if (u4_n<u4_args)
      {
        long double ld_read;
        ld_read=atof(at_args[u4_n]+1);
        if (ld_read<0.0L)
        {
          printf("Module AurelALS300data: Bad laser reference Y value %6.2f. Value is less than zero.\n", (double)ld_read);
          return -1;
        }
        else
        {
          s_data.s_header.u4_lasReferenceY=floor(ld_read*800.0L+0.5L)+0.1L;
          printf("Module AurelALS300data: Laser reference Y set to %6.2f\n", (double)ld_read);
        }
      }
      else
      {
        printf("Module AurelALS300data: Missing modificator '%s' value.\n", at_args[u4_n-1]);
        return -1;
      }
    }
    else if (strcmp(at_args[u4_n],"--probeAReferenceX")==0)
    {
      u4_n++;
      if (u4_n<u4_args)
      {
        long double ld_read;
        ld_read=atof(at_args[u4_n]+1);

        s_data.s_header.i4_masterRefXProbeA=floor(ld_read*800.0L+0.5L)+0.1L;
        printf("Module AurelALS300data: Probe A reference X set to %6.2f\n", (double)ld_read);
      }
      else
      {
        printf("Module AurelALS300data: Missing modificator '%s' value.\n", at_args[u4_n-1]);
        return -1;
      }
    }
    else if (strcmp(at_args[u4_n],"--probeAReferenceY")==0)
    {
      u4_n++;
      if (u4_n<u4_args)
      {
        long double ld_read;
        ld_read=atof(at_args[u4_n]+1);

        s_data.s_header.i4_masterRefYProbeA=floor(ld_read*800.0L+0.5L)+0.1L;
        printf("Module AurelALS300data: Probe A reference Y set to %6.2f\n", (double)ld_read);
      }
      else
      {
        printf("Module AurelALS300data: Missing modificator '%s' value.\n", at_args[u4_n-1]);
        return -1;
      }
    }
    else if (strcmp(at_args[u4_n],"--probeBReferenceX")==0)
    {
      u4_n++;
      if (u4_n<u4_args)
      {
        long double ld_read;
        ld_read=atof(at_args[u4_n]+1);

        s_data.s_header.i4_masterRefXProbeB=floor(ld_read*800.0L+0.5L)+0.1L;
        printf("Module AurelALS300data: Probe B reference X set to %6.2f\n", (double)ld_read);
      }
      else
      {
        printf("Module AurelALS300data: Missing modificator '%s' value.\n", at_args[u4_n-1]);
        return -1;
      }
    }
    else if (strcmp(at_args[u4_n],"--probeBReferenceY")==0)
    {
      u4_n++;
      if (u4_n<u4_args)
      {
        long double ld_read;
        ld_read=atof(at_args[u4_n]+1);

        s_data.s_header.i4_masterRefYProbeB=floor(ld_read*800.0L+0.5L)+0.1L;
        printf("Module AurelALS300data: Probe B reference Y set to %6.2f\n", (double)ld_read);
      }
      else
      {
        printf("Module AurelALS300data: Missing modificator '%s' value.\n", at_args[u4_n-1]);
        return -1;
      }
    }
    else if (strcmp(at_args[u4_n],"--width")==0)
    {
      u4_n++;
      if (u4_n<u4_args)
      {
        long double ld_read;
        ld_read=atof(at_args[u4_n]+1);
        if ((s_data.i4_width<=0.0L))
        {
          printf("Module AurelALS300data: Bad width value %.2f. Value is equal or less than zero.\n", (double)ld_read);
          return -1;
        }
        else
        {
           s_data.i4_width=floor(ld_read*800.0L+0.5L)+0.1L;
          printf("Module AurelALS300data: Width set to %.2f\n", (double)ld_read);
        }
      }
      else
      {
        printf("Module AurelALS300data: Missing modificator '%s' value.\n", at_args[u4_n-1]);
        return -1;
      }
    }
    else if (strcmp(at_args[u4_n],"--height")==0)
    {
      u4_n++;
      if (u4_n<u4_args)
      {
        long double ld_read;
        ld_read=atof(at_args[u4_n]+1);
        if ((ld_read<=0.0L))
        {
          printf("Module AurelALS300data: Bad width value %.2f. Value is equal or less than zero.\n", (double)ld_read);
          return -1;
        }
        else
        {
          s_data.i4_height=floor(ld_read*800.0L+0.5L)+0.1L;
          printf("Module AurelALS300data: Height set to %.2f\n", (double)ld_read);
        }
      }
      else
      {
        printf("Module AurelALS300data: Missing modificator '%s' value.\n", at_args[u4_n-1]);
        return -1;
      }
    }
    else if (strcmp(at_args[u4_n],"--current")==0)
    {
      u4_n++;
      if (u4_n<u4_args)
      {
        long double ld_read;
        ld_read=atof(at_args[u4_n]+1);
        if ((ld_read<1.0)||(ld_read>20.0))
        {
          printf("Module AurelALS300data: Bad current value %.2f. Allow current range is 1 to 20.\n", (double)ld_read);
          return -1;
        }
        else
        {
          s_data.s_header.do_current=ld_read;
          printf("Module AurelALS300data: Current set to %.2f\n", s_data.s_header.do_current);
        }
      }
      else
      {
        printf("Module AurelALS300data: Missing modificator '%s' value.\n", at_args[u4_n-1]);
        return -1;
      }
    }
    else if (strcmp(at_args[u4_n],"--frequency")==0)
    {
      u4_n++;
      if (u4_n<u4_args)
      {
        long double ld_read;
        ld_read=atof(at_args[u4_n]+1);
        if ((ld_read<0.0)||(ld_read>10.0))
        {
          printf("Module AurelALS300data: Bad frequency value %.2f. Allow frequency range is 0 to 10.\n", (double)ld_read);
          return -1;
        }
        else
        {
          s_data.s_header.do_freq=ld_read;
          printf("Module AurelALS300data: Frequency set to %.2f\n", s_data.s_header.do_freq);
        }
      }
      else
      {
        printf("Module AurelALS300data: Missing modificator '%s' value.\n", at_args[u4_n-1]);
        return -1;
      }
    }
    else if (strcmp(at_args[u4_n],"--speed")==0)
    {
      u4_n++;
      if (u4_n<u4_args)
      {
        long double ld_read;
        ld_read=atof(at_args[u4_n]+1);
        if ((ld_read<=0.0L))
        {
          printf("Module AurelALS300data: Bad speed value %.2f. Value is equal or less than zero.\n", (double)ld_read);
          return -1;
        }
        else
        {
          s_data.s_header.do_speed=ld_read;
          printf("Module AurelALS300data: Speed set to %.2f\n", (double)ld_read);
        }
      }
      else
      {
        printf("Module AurelALS300data: Missing modificator '%s' value.\n", at_args[u4_n-1]);
        return -1;
      }
    }
    else if (strcmp(at_args[u4_n],"--cuts")==0)
    {
      u4_n++;
      if (u4_n<u4_args)
      {
        int32_t i4_read;
        i4_read=atoi(at_args[u4_n]+1);
        if ((i4_read<1)||(i4_read>100))
        {
          printf("Module AurelALS300data: Bad cuts value %i. Allow cuts range is 1 to 100.\n", i4_read);
          return -1;
        }
        else
        {
          s_data.s_header.u4_cuts=i4_read;
          printf("Module AurelALS300data: Cuts set to %u\n", s_data.s_header.u4_cuts);
        }
      }
      else
      {
        printf("Module AurelALS300data: Missing modificator '%s' value.\n", at_args[u4_n-1]);
        return -1;
      }
    }
    else if (strcmp(at_args[u4_n],"--transformate")==0)
    {
      s_data.s_header.b_transformate=true;
      printf("Module AurelALS300data: Transformate on.\n");
    }
    else if (strcmp(at_args[u4_n],"--transformateToArea")==0)
    {
      s_data.s_header.b_transToArea=true;
      printf("Module AurelALS300data: Transformate to area on.\n");
    }
    else if (strcmp(at_args[u4_n],"--transformateToZero")==0)
    {
      s_data.s_header.b_transToZero=true;
      printf("Module AurelALS300data: Transformate to zero on.\n");
    }
    else if (strcmp(at_args[u4_n],"--transformateOffsetX")==0)
    {
      u4_n++;
      if (u4_n<u4_args)
      {
        long double ld_read;
        ld_read=atof(at_args[u4_n]+1);
        /*
         if (ld_read<0.0L)
         {
         printf("Module AurelALS300data: Bad transform offset X value %6.2f. Value is less than zero.\n", (double)ld_read);
         return -1;
         }
         else*/
        {
          s_data.s_header.u4_transOffsetY=floor(ld_read*800.0L+0.5L)+0.1L;
          printf("Module AurelALS300data: Transform offset X set to %6.2f\n", (double)ld_read);
        }
      }
      else
      {
        printf("Module AurelALS300data: Missing modificator '%s' value.\n", at_args[u4_n-1]);
        return -1;
      }
    }
    else if (strcmp(at_args[u4_n],"--transformateOffsetY")==0)
    {
      u4_n++;
      if (u4_n<u4_args)
      {
        long double ld_read;
        ld_read=atof(at_args[u4_n]+1);
        /*
        if (ld_read<0.0L)
        {
          printf("Module AurelALS300data: Bad transform offset Y value %6.2f. Value is less than zero.\n", (double)ld_read);
          return -1;
        }
        else*/
        {
          s_data.s_header.u4_transOffsetY=floor(ld_read*800.0L+0.5L)+0.1L;
          printf("Module AurelALS300data: Transform offset Y set to %6.2f\n", (double)ld_read);
        }
      }
      else
      {
        printf("Module AurelALS300data: Missing modificator '%s' value.\n", at_args[u4_n-1]);
        return -1;
      }
    }
    else if (strcmp(at_args[u4_n],"--debug")==0)
    {
      u4_n++;
      if (u4_n<u4_args)
      {
        s_data.i4_debuglevel=atoi(at_args[u4_n]+1);
        printf("Module AurelALS300data: Debug level set to %i\n", s_data.i4_debuglevel);
      }
      else
      {
        printf("Module AurelALS300data: Missing modificator '%s' value.\n", at_args[u4_n-1]);
        return -1;
      }
    }
    else
    {
      printf("Module AurelALS300data: Unknown modificator '%s'.\n", at_args[u4_n]);
      return -1;
    }
  }

  *pv_memory=&s_data;
  return 0;
}
Mac_Fun_Gerber_Module_End(End)
{
  struct sData *ps_data;

  ps_data=(struct sData *)v_memory;

  Data_Save(ps_data);

}

#define COMPARE(a, b) (abs(a-b)<0.000001L)
Mac_Fun_Gerber_Draw_LineSegment(LineSegment)
{
  struct sData *ps_data;

  ps_data=(struct sData *)v_mem;
  //if (b_positive) printf("LINE: POSITIVE: FROM: %3.4f,%3.4f TO: %3.4f,%3.4f\n", (double)ps_From->ld_x, (double)ps_From->ld_y, (double)ps_To->ld_x, (double)ps_To->ld_y);
  //else printf("LINE: NEGATIVE: FROM: %3.4f,%3.4f TO: %3.4f,%3.4f\n", (double)ps_From->ld_x, (double)ps_From->ld_y, (double)ps_To->ld_x, (double)ps_To->ld_y);

  //if (b_incut==true) return 0;

  if (!Data_Add_Element(ps_data, ps_From->ld_x, ps_From->ld_y, ps_To->ld_x, ps_To->ld_y, 7)) // ortho
  {
    printf("Draw element adding failed.\n");
    return -1;
  }
  return 0;
}
Mac_Fun_Gerber_Draw_OvalSegment(OvalSegment)
{
  struct sData *ps_data;

  ps_data=(struct sData *)v_mem;
  //if (b_positive) printf("CIRCLE: POSITIVE: CENTER: %3.4f,%3.4f RADIUS: %3.4f ANGLE: %3.4f to %3.4f \n",
    //                     (double)ps_centre->ld_x, (double)ps_centre->ld_y, (double)ld_radius, (double)ld_aglefrom, (double)ld_agleto);
  //else printf("CIRCLE: NEGATIVE: CENTER: %3.4f,%3.4f RADIUS: %3.4f ANGLE: %3.4f to %3.4f \n",
    //          (double)ps_centre->ld_x, (double)ps_centre->ld_y, (double)ld_radius, (double)ld_aglefrom, (double)ld_agleto);

  //if (b_incut==true) return 0;
  
  if (COMPARE(ld_aglefrom, ld_agleto))
  {
    ld_aglefrom=0.0L;
    ld_agleto=360.0L;
  }

  if (ld_aglefrom<0.0L) ld_aglefrom+=360.0L;
  if (ld_agleto<0.0L) ld_agleto+=360.0L;
  if (ld_aglefrom>ld_agleto)
  {
    ld_agleto+=360;
  }
  ld_aglefrom=(ld_aglefrom/180.0L)*MY_PI;
  ld_agleto=(ld_agleto/180.0L)*MY_PI;

  /*
  // can not use full circle element, befere transofrm can make oval from czrcle
  if (COMPARE(ld_aglefrom, 0.0L)&&COMPARE(ld_agleto, 2.0L*MY_PI))
  {
    // full circle
    printf("Full circle is unsupported now.\n");
    return 0;
  }
  */

  // draw circle by line element

  // 2.0 degree elements
  //if (COMPARE(ld_radiusX, ld_radiusY))
  //if (ld_aglefrom<ld_agleto)
  {
    struct sGerber_Point s_a, s_b;
    //long double ld_radius;

    //ld_radius=ld_radiusX;

    // first point
    s_b.ld_x=cos(ld_aglefrom)*ld_radiusX+ps_centre->ld_x;
    s_b.ld_y=sin(ld_aglefrom)*ld_radiusY+ps_centre->ld_y;
    do
    {
      ld_aglefrom+=((2.0L*MY_PI)/180.0L);

      if (ld_aglefrom>ld_agleto) ld_aglefrom=ld_agleto;

      s_a=s_b;
      s_b.ld_x=cos(ld_aglefrom)*ld_radiusX+ps_centre->ld_x;
      s_b.ld_y=sin(ld_aglefrom)*ld_radiusY+ps_centre->ld_y;

      if (!Data_Add_Element(ps_data, s_a.ld_x, s_a.ld_y, s_b.ld_x, s_b.ld_y, 7)) // ortho
      {
        printf("Draw element adding failed.\n");
        return -1;
      }
    }
    while (ld_aglefrom<ld_agleto);
  }

  return 0;
}

#ifdef __WIN32__
#include <windows.h>
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
  switch (fdwReason)
  {
    case DLL_PROCESS_ATTACH:
      // attach to process
      // return FALSE to fail DLL load
      // inicializace manualni
      break;

    case DLL_PROCESS_DETACH:
      // detach from process
      // sem dat ukoncovaci funkci
      break;

    case DLL_THREAD_ATTACH:
      // attach to thread
      // vytvoreni vlakna
      break;

    case DLL_THREAD_DETACH:
      // detach from thread
      // konec vlakna
      break;
  }
  return TRUE; // succesful
}
#endif // __WIN32__
