/* Title: cmdline.c
 * Author: Jed Marti KI7NNP
 * Description: Command line arguments for inductor program.
 * Revision History: (Created Sat Jan 27 12:22:36 2024)
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <string.h>

#include "inductor.h"
#include "equations.h"

char *ENames[] = {
   "ARRLOriginal",
   "ARRLTurns",
   "ARRLcspacing",
   "ARRLall22",
   "ARRLall",
   "Simple",
   "Equation8",
   "EquationA",
   "EquationD",
   "EquationF",
   "EquationG",
   "EquationH",
   "EquationI",
   "RFC",
   "RF1",
   "Lundin",
   "Miller"};
   
// Wire gauge.
int32_t W = 22;

// Sizes
double maxlength = inches2meters(3.0);
double minlength = inches2meters(0.05);
double maxradius = inches2meters(1.0);
double minradius = inches2meters(0.0625);

// Size divisions.
double reslength = 100.0;
double resradius = 100.0;

// Inductance requested.
double uh = -1.0;

// Equation selected - default is ARRLOriginal.
uint8_t E = eqARRLOriginal;

// The turns range.
int32_t minturns = 1;
int32_t maxturns = 50;

#define nxt(err) if (++i >= argc) { fprintf(stderr, "%s missing argument\n", err); exit(-1); }

void cmdline(int32_t argc, char *argv[])
{
  int32_t i;
  int32_t j;
  
  if (argc < 2)
  {
    printf("Usage: inductor [-key value]\n\
  -gauge nnnn   Wire gauge (#%d)\n\
  -maxlength float [inches|mm]  Maximum length (%g\")\n\
  -minlength float [inches|mm]  Minimum length (%g\")\n\
  -maxradius float [inches|mm]  Maximumm radius (%g\")\n\
  -minradius float [inches|mm]  Minimum radius (%g\")\n\
  -minturns int     Minimum turns to test (%d)\n\
  -maxturns int     Maximum turns to test (%d)\n\
  -reslength float  Length resolution (%g)\n\
  -resradius float  Radius resolution (%g)\n\
  -equation string   Which equation to use (%s)\n\
  float     Inductance in microHenrys (required)\n", W, meters2inches(maxlength),
           meters2inches(minlength), meters2inches(maxradius), meters2inches(minradius),
           minturns, maxturns,
           reslength, resradius, ENames[E]);

    printf("Equations:\n");
    for (i = 0; i < sizeof(ENames) / sizeof(char*); ++i)
      printf("  %s%c\n", ENames[i], i == E?'*':' ');
    exit(0);
  }

  for (i = 1; i < argc; )
  {
    // Wire gauge.
    if (strcasecmp(argv[i], "-gauge") == 0)
    {
      nxt("-gauge");
      W = atoi(argv[i]);
      if (W < 14 || W > 32)
      {
        fprintf(stderr, "-gauge %d illegal [14 .. 32]\n", W);
        exit(-1);
      }
      ++i;
    }

    // maximum length.
    else if (strcasecmp(argv[i], "-maxlength") == 0)
    {
      nxt("-maxlength");
      maxlength = atof(argv[i]);
      if (++i >= argc)
      {
        maxlength = inches2meters(maxlength);
        return;
      }
      else if (strcasecmp(argv[i], "inches") == 0)
      {
        maxlength = inches2meters(maxlength);
        ++i;
      }
      else if (strcasecmp(argv[i], "mm") == 0)
      {
        maxlength /= 1000.0;
        ++i;
      }
      else if (strcasecmp(argv[i], "cm") == 0)
      {
        maxlength /= 100;
        ++i;
      }
    }

    // minimum length.
    else if (strcasecmp(argv[i], "-minlength") == 0)
    {
      nxt("-minlength");
      minlength = atof(argv[i]);
      if (++i >= argc)
      {
        minlength = inches2meters(minlength);
        return;
      }
      else if (strcasecmp(argv[i], "inches") == 0)
      {
        minlength = inches2meters(minlength);
        ++i;
      }
      else if (strcasecmp(argv[i], "mm") == 0)
      {
        minlength /= 1000.0;
        ++i;
      }
      else if (strcasecmp(argv[i], "cm") == 0)
      {
        minlength /= 100;
        ++i;
      }
    }

    // maximum radius
    else if (strcasecmp(argv[i], "-maxradius") == 0)
    {
      nxt("-maxradius");
      maxradius = atof(argv[i]);
      if (++i >= argc)
      {
        maxradius = inches2meters(maxradius);
        return;
      }
      else if (strcasecmp(argv[i], "inches") == 0)
      {
        maxradius = inches2meters(maxradius);
        ++i;
      }
      else if (strcasecmp(argv[i], "mm") == 0)
      {
        maxradius /= 1000.0;
        ++i;
      }
      else if (strcasecmp(argv[i], "cm") == 0)
      {
        maxradius /= 100;
        ++i;
      }
    }

    // minimum radius
    else if (strcasecmp(argv[i], "-minradius") == 0)
    {
      nxt("-minradius");
      minradius = atof(argv[i]);
      if (++i >= argc)
      {
        minradius = inches2meters(minradius);
        return;
      }
      else if (strcasecmp(argv[i], "inches") == 0)
      {
        minradius = inches2meters(minradius);
        ++i;
      }
      else if (strcasecmp(argv[i], "mm") == 0)
      {
        minradius /= 1000.0;
        ++i;
      }
      else if (strcasecmp(argv[i], "cm") == 0)
      {
        minradius /= 100;
        ++i;
      }
    }

    // Length resolution - the number of steps to test between minimum and maximum.
    else if (strcasecmp(argv[i], "-reslength") == 0)
    {
      nxt("-reslength");
      reslength = atof(argv[i]);
      if (reslength < 1.0)
      {
        fprintf(stderr, "-reslength %g illegal (must be >= 1.0)\n", reslength);
        exit(-1);
      }
    }
        
    // Radius resolution - the number of steps to test between minimum and maximum.
    else if (strcasecmp(argv[i], "-resradius") == 0)
    {
      nxt("-resradius");
      resradius = atof(argv[i]);
      if (resradius < 1.0)
      {
        fprintf(stderr, "-resradius %g illegal (must be >= 1.0)\n", resradius);
        exit(-1);
      }
    }

    // Minimum number of turns to test. Must be > 0.
    else if (strcasecmp(argv[i], "-minturns") == 0)
    {
      nxt("-minturns");
      minturns = atoi(argv[i]);
      if (minturns < 1)
      {
        fprintf(stderr, "-minturns %d is illegal, must be > 0\n", minturns);
        exit(-1);
      }
    }

    // Maximum number of turns to test. Must be > 0. If > 50, then give warning (later).
    // We don't change low-high until later.
    else if (strcasecmp(argv[i], "-maxturns") == 0)
    {
      nxt("-maxturns");
      maxturns = atoi(argv[i]);
      if (minturns < 1)
      {
        fprintf(stderr, "-maxturns %d is illegal, must be > 0\n", minturns);
        exit(-1);
      }
    }
        
    // A number is probably the uh.
    else if ((argv[i][0] >= '0' && argv[i][0] <= '9') || argv[i][0] == '.')
    {
      uh = atof(argv[i]);
      ++i;
    }

    // Check for equation.
    else
    {
      for (j = 0; j < sizeof(ENames) / sizeof(char*); ++j)
      {
        if (strcasecmp(ENames[j], argv[i]) == 0)
        {
          E = j;
          break;
        }
      }
      if (j >= sizeof(ENames) / sizeof(char*))
      {
        fprintf(stderr, "Unknown option %s\n", argv[i]);
        exit(-1);
      }
      ++i;
    }
  }
}


// EOF
