/************************************************************
**
** Application: SyncDiscs
**
** Title:       c.main
**
*************************************************************/

/*
*
* Copyright (c) 2017, David Pilling and Chris Johnson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the copyright holder nor the names of their
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

/* Include files */
/* from standard clib */
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <locale.h>

#include "Tasklib:h.os"
#include "Tasklib:h.wimp"
#include "Tasklib:h.wimpt"
#include "Tasklib:h.werr"
#include "Tasklib:h.transform"
#include "Tasklib:h.wos"
#include "Tasklib:h.err"
#include "Tasklib:h.task"
#include "Tasklib:h.poll"
#include "Tasklib:h.temp"
#include "Tasklib:h.scrap"
#include "Tasklib:h.fsx"
#include "Tasklib:h.etc"
#include "Tasklib:h.pane"
#include "Tasklib:h.bits"
#include "Tasklib:h.bf"
#include "Tasklib:h.constants"
#include "Tasklib:h.xhelp"
#include "Tasklib:h.mlo"
#include "Tasklib:h.mym"
#include "Tasklib:h.urllaunch"
#include "Tasklib:h.log"
#include "Tasklib:h.deb"
#include "Tasklib:h.conf"
// #include "Tasklib:h.message"



/* from application */
#include "revision.h"

#include "h.debugDefs"
#include "h.dbox"
#include "h.reslink"
#include "h.arcs"
#include "h.zone"
#include "h.progress"
#include "h.syncdiscs"
#include "h.main"
#include "dirlist.h"



/************************************************************/


char   * version = "1.30";
char   * datestring = "(9 Jan 2026)";

/**********************************************/

#define WEB_BUTTON 8         /* web button icon ID in Info window */

/* paths for the help files */
#define HTML_HELP_FILE     "<SyncDiscsRes$Dir>.Docs.help/html"
#define TEXT_HELP_FILE     "<SyncDiscsRes$Dir>.Docs.help/txt"

//// #define INFO_MSG_FILE      "<SyncDiscsRes$Dir>.InfoMsg"


/**********************************************/




/************************************************************/

void terminate (void)
{
  os_error   *err;
  int         yes_quit = TRUE;               /* for yes/no confirmation */


  /* Discourage quitting while a job is still running */
  if (sync_running)
  {
    err = confirm (CONYN, &yes_quit, "There is a synchronization job in progress. "
                                     "Do you really wish to quit?");
  }
  if (yes_quit)
  {
    dirlist_save ();
    event (EVENT_ENDPROGRAM, NULL, 0);
    scrapfinit ();
////    message_finit ();
    report (finittask ());
    exit (0);
  }
}




/************************************************************/

static os_error *terminatemessage (wimp_msgstr * msg, int *ack)
{
  terminate ();
  USE (msg);
  USE (ack);
  return (NULL);
}



/************************************************************/

static os_error *uribouncemessage (wimp_msgstr * msg, int *ack)
{
  return (urllaunch_bounce (msg));
  USE (ack);
}



/************************************************************/

static os_error *taskclosemessage (wimp_msgstr * msg, int *ack)
{
  int         i;

  /*********************************************************************
   *                                                                   *
   * make a copy of the terminating task handle - used by the file     *
   * copy or move routines to wait for a particular thread to finish   *
   * when allowing only one FA or when doing a move + copy             *
   *                                                                   *
   *********************************************************************/

  endtaskhandle = msg->hdr.task;

  /* Only do the accounting if we are multitasking and not doing a
   * comparison run.
   */

  /* check the task handle and if it corresponds to one of those
   * filer_actions initiated by ourselves, remove it from the list */

  for (i = 0; i < farunning.count; i++)
  {
    if (farunning.handles[i] == endtaskhandle)
    {
      break;
    }
  }

  /* If the above loop ran to completion with no match then
   * i = farunning.count. Check for a match using this criteria.
   */
  if (i < farunning.count)
  {
    /* We must have a match of task handle */
    if (i < (farunning.count - 1))
    {
      /* if not the last task handle in the list then we move the handles
       * down in the list. If the last one - no need to move anything
       * down
       * i is already set to the starting value
       */
      for ( ; i < (farunning.count - 1); i++)
      {
        farunning.handles[i] = farunning.handles[i + 1];
      }
    }
    farunning.count--;
    /* and update the fa count in progress window */
    progress_update_fa_count_field();
  }


  return (NULL);
  USE (ack);
  USE (msg);
}


/************************************************************/

/* deal with click on web button in info window */

static os_error *infoicon (int handle, int userhandle, wimp_mousestr * m)
{
  os_error   *err;

  err = NULL;

  switch (m->i)
  {
  case WEB_BUTTON:
    err = urllaunch_broadcast (WEB_URL);
    /* delete the menu unless the ADJUST button was used */
    if (m->bbits != 1) zapmenu ();
    break;
  }

  return (err);

  USE (handle);
  USE (userhandle);
}




/************************************************************/

static os_error *writebootfile (wimp_msgstr * msg, int *ack)
{
  char        string[256];
  int         handle;

  handle = msg->data.savedesk.filehandle;
  sprintf (string, "Run %s\n", getenv ("SyncDiscs$Dir"));
  return (fs_write (handle, string, strlen (string)));
  USE (ack);
}



/************************************************************/

static os_error *addmessages (void)
{
  os_error   *err;

  err = addmessage (writebootfile, wimp_SAVEDESK);
  if (!err) err = addmessage (terminatemessage, wimp_MCLOSEDOWN);
  if (!err) err = addmessage (uribouncemessage, wimp_MURI_RETURNRESULT);
  if (!err) err = addmessage (taskclosemessage, wimp_MCLOSETASK);

  return (err);
}



/************************************************************/

/* open info window and pass back pointer */

static os_error *infodynamic (int *menu, int *handle)
{
  os_error   *err;
  static int  infowhandle;

  err = NULL;

  if (menu[0] == 0)
  {
    if (!infowhandle)
    {
      err = createwindow (TINFO, &infowhandle);
      if (!err)
      {
        addclickevent (infoicon, infowhandle, 0);
        addhelpevent(NULL,infowhandle,TINFO);
      }
    }
    writeicon (infowhandle, 1, wimpt_programname ());

#ifdef RELEASE
    writeiconf (infowhandle, 7, "%s %s", version, datestring);
#else
    writeiconf (infowhandle, 7, "Dev %s %s", REVISION, __DATE__);
#endif

    *handle = infowhandle;
  }

  return (err);
}




/**********************************************************************
 * Following function tries to display the application help file.     *
 * Either html or text, in that order.                                *
 * If neither is found - shows a warning message.                     *
 * The original method using a !Help file in the application          *
 * directory which ran the html or text file, caused an               *
 * error if itself or the files were not found                        *
 **********************************************************************/

static os_error *show_help_file (void)
{
  os_error   *err;
  char       cmd[256];
  char      *file;
  int        type = 0;

  err = NULL;
  file = NULL;

  /* check that a browser has been seen by the filer */
  /* if so we can try to run the html help file */
  /* first check that it exists */
  fs_exists (HTML_HELP_FILE, &type);
  if (os_read_var_size ("Alias$@RunType_FAF") && type)
  {
    file = HTML_HELP_FILE;
  }
  else
  {
    /* we can try to run the text help file instead */
    /* check that it exists */
    fs_exists (TEXT_HELP_FILE, &type);
    if (type)
    {
      file = TEXT_HELP_FILE;
    }
  }
  if (file)
  {
    /* run the file */
    sprintf(cmd,"Filer_Run %s",file);
    err = os_cli ( cmd ) ;
  }
  else
  {
    /* give user a warning message */
    messagebox ("Neither the html nor the text help file can be found");
  }
  return (err);
}




/************************************************************/

static os_error *infodecode (int *menu)
{
  os_error   *err;

  err = NULL;


  switch (menu[0])
  {
  case 1:
    show_help_file ();
    break;

  case 2:
    if (sync_running)
    {
      err = progress_open ();
    }
    else
    {
      err = opensyncdiscs ();
    }
    break;

  case 3:
    err = open_settings ();
    break;

  case 4:
    terminate ();
    break;
  }

  return (err);
}






/************************************************************/

static os_error *iconbar (int handle, int userhandle, wimp_mousestr * m)
{
  os_error   *err;

  err = NULL;

  if (m->i == iconbaricon)
  {
    if (m->bbits == MENU_BUTTON)
    {
      err = openupmenu (MINFO);
    }
    else
    {
      if (m->bbits == SELECT_BUTTON)
      {
        if (sync_running)
        {
          if (progress_handle)
            err = opensyncdiscs ();
          else
            err = progress_open ();
        }
        else
        {
          if (progress_handle) progress_close (0, 0);
          err = opensyncdiscs ();
        }
      }
      else
      {
        /* Must be the ADJUST button - open settings */
        err = open_settings ();
      }

    }
  }

  return (err);

  USE (userhandle);
  USE (handle);
}




/************************************************************/

static os_error *setupmenus (void)
{
  os_error   *err;

  err = addclickevent (iconbar, -2, 0);

  setmenufns (MINFO, infodecode, infodynamic);
  setmenudynamic (MINFO, 0);
  setmenuflags (MINFO, MFINFO);

  return (err);
}




/************************************************************/

int main (int argc, char *argv[])
{
  os_error  *err;
  int        quit;
  int        handle_already_running;
  int        type;

  char * temp_msg;

  setlocale (LC_ALL, "ISO8859-1");

  /******************************************************************************
   * It is unwise to run more than one instantiation of SyncDiscs.              *
   * Check if there is a task already running named "SyncDiscs".                *
   * If there is, then our action depends on whether this version was           *
   * invoked with command line parameters or not.                               *
   * If there are no command line parameters we can quit immediately without    *
   * initialising as a wimp task.                                               *
   * If there are command line parameters, we must first transfer these to      *
   * the running version before we quit. In order to do so, we must             *
   * initialise as a wimp task to send a message to the first                   *
   * running task.                                                              *
   ******************************************************************************/

  err = wos_tasknametohandle ("SyncDiscs", &handle_already_running);
  if (handle_already_running)
  {
    /* there is a version already runing */
    if (argc < 2)
    {
      /*****************************************************************************
       * This version has been run without any command line arguments, probably    *
       * by double clicking on the SyncDiscs icon in a filer display. We can just  *
       * exit immediately and quietly. There is essentially no tidying up to do.   *
       *****************************************************************************/
      exit (0);
    }
  }

  /* Now we need to initialise with the wimp */

  err = inittask (APP_NAME, APP_NAME, "!SyncDiscs",
                               "<SyncDiscsRes$Dir>", NULL, NULL);
  if (err)
  {
    report (err);
    exit (0);
  }

#ifdef FROM_RUN
  log_init (SET_LOG_FROM_RUN_FILE, LOGGING_ON, LOG_TO_REPORTER, CLEAR_LOGFILE);
#else
  log_init (SET_LOG_FROM_APP, LOGGING_ON, LOG_TO_REPORTER, CLEAR_LOGFILE);
#endif

  debugenable (NULL);


  if (!err) err = seticonbar ("!SyncDiscs");
  if (!err) err = resinit ("<SyncDiscsRes$Dir>");
  if (!err) err = addmessages ();
  if (!err) err = menulostart ("<SyncDiscsRes$Dir>", "Menus");
  if (!err) err = setupmenus ();
  if (!err) err = scrapinit (APP_NAME, APP_NAME);
  if (!err) err = arcsinit ();
  init_default_settings ();
  if (!err) err = configinit ();
  if (!err) err = config2init ();
////  if (!err) err = zoneinit ();  Moved to syncdiscs fn
  if (!err) err = progress_init ();
  if(!err) err=addhelp ( "<SyncDiscsRes$Dir>", "Help" );
  jobloadinit ();
  dirlist_load ();

  if(!err) err=addhelpevent(NULL,-2,ICONBARTAG);

////  if (!err) err = message_initialise (INFO_MSG_FILE);

  /* check that a new location zone file exists */
  fs_exists (NEW_DEFAULT_ZONE_FILE, &type);
  if (type == 0)
  {
    /* File not present. Is zone file dir present? */
    fs_exists (ZONE_FILE_DIR, &type);
    if (type == 0)
    {
      /* Not there, so create it */
      fs_cdir (ZONE_FILE_DIR);
    }
    /* Is there an old location zone file? */
    fs_exists (OLD_DEFAULT_ZONE_FILE, &type);
    /* If there is, copy it in to new location */
    if (type == 1)
    {
      /* copy it in to new location */
      fs_copyobjects (OLD_DEFAULT_ZONE_FILE, NEW_DEFAULT_ZONE_FILE, 0);
    }
  }


  event (EVENT_RUNPROGRAM, NULL, 0);

  if (err)
  {
    report (err);
    terminate ();
  }


  if (argc > 1)
  {
    if (handle_already_running)
    {
      /*********************************************************************
       * We are a second task and must pass the cmd line parameters        *
       * to the earlier task. There are two possibilities which must       *
       * be dealt with differently.                                        *
       *                                                                   *
       * 1. This is the result of running SyncDiscs with a command         *
       *    line set of parameters. The simplest way to deal with this     *
       *    is to write the parameters to a file and then send a message   *
       *    to SD no. 1 to tell it to load the file.                       *
       *                                                                   *
       * 2. This is the result of 'running' a Syncjob file. In this case   *
       *    there will be one command line parameter, viz. the full path   *
       *    of the file being run. Thus we need only to pass the path to   *
       *    SD no. 1 for it to load the file.                              *
       *********************************************************************/

      wimp_msgstr msg;
      buffer     bf;
      char     * p;


      p = argv[1];
      if ((argc == 2) && (p[0] != '-'))
      {
        /* The first and only argument does not start with the - char
         * We assume it is the filename of a syncjob being 'run'
         * All we need to do is to pass the file path to SD no. 1
        */

        /* send a DataOpen message to SD no. 1 to load the file */
        msg.hdr.your_ref = 0;
        msg.hdr.action = wimp_MDATAOPEN;
        msg.data.dataload.w = -1;
        msg.data.dataload.i = 0;
        msg.data.dataload.x = 0;
        msg.data.dataload.y = 0;
        msg.data.dataload.size = 0;
        msg.data.dataload.type = SYNCDISCS_FILETYPE;
        strcpy (msg.data.dataload.name, argv[1]);
        /* length of message block must be rounded up to a whole number
           of words */
        msg.hdr.size = 44 + ((strlen (argv[1]) + 4) & 0xFFFFFFFC);
        wimp_sendmessage (wimp_ESEND, &msg, handle_already_running);
        /* we have sent the message so now just quit */
        terminate ();
      }
      else
      {
        int i;

        /* Open the file */
        err=bf_open(JOB_TRANSFER_FILENAME, 'w', DEFBUFFSIZE, &bf);
        if (!err)
        {
          /* loop through and parse the args to write to file */
          /* some args are switches, others require a following value */
          for (i = 1; i < argc; i++)
          {
            p = argv[i];
            /* is the first char a ~? */
            if (p[0] == '~')
            {
              /* these are nulling single arguments */
              p++;
              if (!cstrcmp (p, "newer"))
                err = bf_printf (&bf, "Newer 0\n");
              else if (!cstrcmp (p, "extra"))
                err = bf_printf (&bf, "Extra 0\n");
              else if (!cstrcmp (p, "over"))
                err = bf_printf (&bf, "Overwrite 0\n");
              else if (!cstrcmp (p, "log"))
                err = bf_printf (&bf, "Log 0\n");
              else if (!cstrcmp (p, "zone"))
                err = bf_printf (&bf, "UseZoneFile 0\n");
            }
            else
            {
              if (p[0] == '-')
              {
                p++;
                /* arguments needing a following value */
                if (!cstrcmp (p, "primary"))
                {
                  i++;
                  if (i < argc)
                    err = bf_printf (&bf, "Primary %s\n", argv[i]);
                }
                else if (!cstrcmp (p, "secondary"))
                {
                  i++;
                  if (i < argc)
                    err = bf_printf (&bf, "Secondary %s\n", argv[i]);
                }
                else if (!cstrcmp (p, "scrap"))
                {
                  i++;
                  if (i < argc)
                    err = bf_printf (&bf, "Scrap %s\n", argv[i]);
                }
                else if (!cstrcmp (p, "log"))
                {
                  i++;
                  if (i < argc)
                    err = bf_printf (&bf, "LogFile %s\n", argv[i]);
                    if (!err) err = bf_printf (&bf, "Log 1\n");
                }
                else if (!cstrcmp (p, "zone"))
                {
                  i++;
                  if (i < argc)
                    err = bf_printf (&bf, "ZoneFile %s\n", argv[i]);
                    if (!err) err = bf_printf (&bf, "UseZoneFile 1\n");
                }
                /* the single switches */
                /* we ignore the -quit parameter */
                else if (!cstrcmp (p, "newer"))
                  err = bf_printf (&bf, "Newer 1\n");
                else if (!cstrcmp (p, "extra"))
                  err = bf_printf (&bf, "Extra 1\n");
                else if (!cstrcmp (p, "over"))
                  err = bf_printf (&bf, "Overwrite 1\n");
              }
            }
            if (err) break;
          }
          /* when done close the file */
          /* set the filetype to syncdisc */
          err = bf_closec (&bf, err, JOB_TRANSFER_FILENAME, SYNCDISCS_FILETYPE);
          /* send a DataOpen message to SD no. 1 to load the file */
          msg.hdr.your_ref = 0;
          msg.hdr.action = wimp_MDATAOPEN;
          msg.data.dataload.w = -1;
          msg.data.dataload.i = 0;
          msg.data.dataload.x = 0;
          msg.data.dataload.y = 0;
          msg.data.dataload.size = 0;
          msg.data.dataload.type = SYNCDISCS_FILETYPE;
          strcpy (msg.data.dataload.name, JOB_TRANSFER_FILENAME);
          /* length of message block must be rounded up to a whole number
             of words */
          msg.hdr.size = 44 + ((strlen (JOB_TRANSFER_FILENAME) + 4) & 0xFFFFFFFC);
          wimp_sendmessage (wimp_ESEND, &msg, handle_already_running);
        }

        /* we have sent the message so now just quit */
        terminate ();
      }
    }
    else
    {
      char     * p;

      /* we are the only syncdiscs */
      p = argv[1];
      if ((argc == 2) && (p[0] != '-'))
      {
        /* The first and only argument does not start with the - char
         * We assume it is the filename of a syncjob being 'run'
         * by double clicking on a job file
         * Just load the file directly
        */
        jobload2 (argv[1]);
      }
      else
      {
        /* started with cmd line parameters so act immediately on them */
        report (commandline (argc, argv, &quit));
        if (quit)
          terminate ();
      }
    }
  }


  runtask ();

}





/*************  End of c.main  ***********************/

