/* OFFSETDATE.C - generate a date that's offset from the system date

            Written by M.C.Gregorie.

            Version history
               
            1.0   28/07/11   Initial release
*/

#define VERSION         "1.0"
#define COPYRIGHT       "(c) M.C.Gregorie, 2011"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <environ.h>
#include <adjustdate.h>

#include "offsetdate.h"

/*
   This function scans the command line for options and does
   all the associated setup.
*/
int readargs(int argc,
             char *argv[],
             int flags[],
             char **offset,
             char **element,
             char **format)
{
   int         i; 
   int         opt;
   char        *unset = "**unset**";
   char        *zero = "0";

   /* initialise flags */

   for (i=0 ; i<FLAGCNT ; i++) flags[i] = FALSE;
   *offset = zero;
   *element = unset;
   *format = unset;

   /* set up options from the command line */

   optmaybe = MAYBEMARK;
   optbad = BADMARK;
   optind = 1;
   
   while ((opt=getopt(argc,argv,OPTLIST)) != EOF)   
   {
      switch (opt) {
         case 0:         continue;
         case BADMARK:   return(opt);
         case '?':       flags[HELP] = TRUE;       
                         break;
         case 'd':       flags[DEBUG] = TRUE;
                         break;
         case 'e':       flags[ELEMENT] = TRUE;
                         *element = get_space(max(strlen(optarg),1));
                         strcpy(*element, optarg);
                         break;
         case 'f':       flags[FORMAT] = TRUE;
                         *format = get_space(max(strlen(optarg),1));
                         strcpy(*format, optarg);
                         break;
         case 'o':       flags[OFFSET] = TRUE;
                         *offset = get_space(max(strlen(optarg),1));
                         strcpy(*offset, optarg);
                         break;
         case 't':       flags[TRUNCATE] = TRUE;
                         break;
         default :       error(argv[0],
                               "impossible happened parsing options",
                               "");
      }
   }
   return(OK);
}

/*
   Show the punter what the options are
*/
void showhelp()
{
   printf("\noffsetdate v%s %s\n\n",VERSION,COPYRIGHT);
   printf("Syntax  : offsetdate [<opts>]\n");
   printf("Function: Output a string containing a date offset from the\n");
   printf("          system date by '-o=offset' '-e=element', formatted\n");
   printf("          by '-f=format' and sent to stdout.\n");
   printf("          'offset'  is a signed integer.\n");
   printf("          'element' is one of YEAR, YEARSTART, YEAREND, MONTH\n");    
   printf("                    MONTHSTART, MONTHEND, DAY, HOUR, MINUTE,\n");
   printf("                    or SECOND and is caseless.\n");
   printf("          'format'  uses strftime() format directives.\n");
   printf("Options :\n");
   printf("     -d           Debug mode.\n");
   printf("     -e=element   Required. Date/time element to be offset.\n");
   printf("     -f='format'  Required. strftime() format string.\n");
   printf("                  Must be quoted if spaces are included.\n");
   printf("     -o=offset    Signed integer offset value. Defaults to 0.\n");
   printf("     -t           Truncate days to month end.\n");
   printf("                  Default is roll over into the start of\n");
   printf("                  the next month.\n");
}

/*
   The main program starts here
   ----------------------------
*/
int main(int argc, char *argv[])
{
   int   flags[FLAGCNT];
   char  *offstr;
   int   offset;
   char  *element;
   char  *format;
   char  *fdate;
   int   reply;

   /*
      Parse and set up command options
   */
   setprog(argv[0]);
   if (readargs(argc,argv,flags, &offstr, &element, &format) == BADMARK)
      return(1);

   /*
      If help was asked for, give it and quit
   */
   if (flags[HELP]) 
   {
      showhelp();
      return(0);
   }

   if (!flags[ELEMENT])
      error(progname(), "mandatory parameter omitted:", "-e=element");

   if (!flags[FORMAT])
      error(progname(), "mandatory parameter omitted:", "-f='format'");

   /*
      Convert 'offset' to an int and validate the arguments.
   */
   offset = atoi(offstr);
   strupr(element);
   if (flags[DEBUG])
      logmsg("offset=%d\nelement=%s\nformat='%s'\ntruncate=%s",
             offset,
             element,
             format,
             (flags[TRUNCATE] ? "ON" : "OFF"));

   /*
      Generate an offset date
   */
   ajdebug(flags[DEBUG]);
   if (flags[TRUNCATE])
      ajtruncate(ON);
      
   ajsetnow();
   if (flags[DEBUG])
      logmsg("basedate set to %s",
             ajformatdate("%Y-%m-%s %H:%M:%S"));
              
   if (strcmp(element, "DAY") == 0)
      ajoffsetdate(offset, DAY);
   else
   if (strcmp(element, "HOUR") == 0)
      ajoffsetdate(offset, HOUR);
   else
   if (strcmp(element, "MINUTE") == 0)
      ajoffsetdate(offset, MIN);
   else
   if (strcmp(element, "SECOND") == 0)
      ajoffsetdate(offset, SEC);
   else    
   if (strcmp(element, "MONTH") == 0)
      ajmonth(offset, KEEPDAY);
   else
   if (strcmp(element, "MONTHSTART") == 0)
      ajmonth(offset, FIRSTDAY);
   else
   if (strcmp(element, "MONTHEND") == 0)
      ajmonth(offset, LASTDAY);
   else
   if (strcmp(element, "YEAR") == 0)
      ajyear(offset, KEEPDATE);
   else
   if (strcmp(element, "YEARSTART") == 0)
      ajyear(offset, FIRSTDAY);
   else
   if (strcmp(element, "YEAREND") == 0)
      ajyear(offset, LASTDAY);
   else
      error(progname(), "unknown date element:", element);

   if (ajerror())
      error(progname(), ajgeterror(), "");

   if (ajgetdate() < 0)
      error(progname(),
            "The required date is outside the UNIX date range",
            "");

   fdate = ajformatdate(format);
   if (ajerror())
      error(progname(), ajgeterror(), "");

   printf("%s\n", fdate);
   return(0);   
}
