/*
 * IssueTracker Main   (C) 1996 John Haubrich
 *                              All Rights Under Copyright Reserved
 *
 * Version 1.0
 *
 * Written using SAS/C 6.56
 * Using Magic User Interface (MUI) by Stefan Stuntz
 *
 * By John Haubrich
 *
 *
 * Version~ Date~~~~~~~ Comments~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * -------  ----        --------
 *             ;
 */

#include "common.h"


extern struct MUI_Command *RXCommands;


/*
 * GLOBAL VARIABLES ----------------------------------
 */
struct MyGlobals  MG;
char              GL_szFault[256];

struct MainWindow   MAIN;


/*
 * DEFINES -------------------------------------------
 */


/*
 * LIBRARY VARIABLES ---------------------------------
 */

struct Library       *AslBase       = NULL;
struct DosBase       *DosBase       = NULL;
struct GfxBase       *GfxBase       = NULL;
struct Library       *IconBase      = NULL;
struct IntuitionBase *IntuitionBase = NULL;
struct Library       *MUIMasterBase = NULL;
struct Library       *UtilityBase   = NULL;
struct Library       *WorkbenchBase = NULL;


#ifdef LATTICE
int CXBRK(void) { return(0); }
void __regargs __chkabort(void) { return; }
#endif


/*
 * SUBROUTINES ---------------------------------------
 */
//
// funUpdateStatsGUI(): updates GUI with stats numbers in MG.lIssuesGrid
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void fnUpdateStatsGUI( void )
{
   LONG  i, j;


   for ( j = 0; j < STATUS_COUNT + 1; j++ )
   {
      for ( i = 0; i < PRIORITY_COUNT + 1; i++ )
      {
         sprintf( MG.szIssuesGrid[ j ][ i ], "%ld", MG.lIssuesGrid[ j ][ i ] );
         set( MAIN.TXT_IssuesGrid[ j ][ i ], MUIA_Text_Contents, MG.szIssuesGrid[ j ][ i ] );
      }
   }
}

//
// fnCalcTotals(): calculate totals fields
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void fnCalcTotals()
{
   LONG  i, j;


   // clear totals fields
   for ( j = 0; j < STATUS_COUNT + 1; j++ )
   {
      MG.lIssuesGrid[ j ][ PRIORITY_COUNT ] = 0;
   }
   for ( i = 0; i < PRIORITY_COUNT + 1; i++ )
   {
      MG.lIssuesGrid[ STATUS_COUNT ][ i ] = 0;
   }

   // count issues for each totals field
   for ( j = 0; j < STATUS_COUNT; j++ )
   {
      for ( i = 0; i < PRIORITY_COUNT; i++ )
      {
         MG.lIssuesGrid[ j ][ PRIORITY_COUNT ] += MG.lIssuesGrid[ j ][ i ];
         MG.lIssuesGrid[ STATUS_COUNT ][ i ]   += MG.lIssuesGrid[ j ][ i ];
      }
   }

   // calc grand total
   for ( j = 0; j < STATUS_COUNT; j++ )
   {
      MG.lIssuesGrid[ STATUS_COUNT ][ PRIORITY_COUNT ] += MG.lIssuesGrid[ j ][ PRIORITY_COUNT ];
   }
}

//
// fnTallyRecordAdd(): add stats from this record to the grid
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void fnTallyRecordAdd( LONG lRec )
{
   LONG  rechold[ 4 ];  // 3 columns in list -- we only care about the LONGs in the first two...


   DoMethod( MAIN.DLIS_List, MUIM_DataList_GetRecordArray, lRec, &rechold );
   MG.lIssuesGrid[ rechold[0] ][ rechold[1] ] += 1;
}

//
// fnTallyRecordSubtract(): subtract stats from this record to the grid
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void fnTallyRecordSubtract( LONG lRec )
{
   LONG  rechold[ 4 ];  // 3 columns in list -- we only care about the LONGs in the first two...


   DoMethod( MAIN.DLIS_List, MUIM_DataList_GetRecordArray, lRec, &rechold );
   MG.lIssuesGrid[ rechold[0] ][ rechold[1] ] -= 1;
}

//
// fnClearStats(): set counters to zero
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void fnClearStats( void )
{
   LONG  i, j;


   // clear stats
   for ( j = 0; j < STATUS_COUNT + 1; j++ )
   {
      for ( i = 0; i < PRIORITY_COUNT + 1; i++ )
      {
         MG.lIssuesGrid[ j ][ i ] = 0;
         strcpy( MG.szIssuesGrid[ j ][ i ], "" );
         set( MAIN.TXT_IssuesGrid[ j ][ i ], MUIA_Text_Contents, MG.szIssuesGrid[ j ][ i ] );
      }
   }
}

//
// fnUpdateAllStats():
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void fnUpdateAllStats( void )
{
   LONG  lEntries;
   LONG  l;


   fnClearStats();
   get( MAIN.DLIS_List, MUIA_List_Entries, &lEntries );
   for ( l = 0; l < lEntries; l++ )
   {
      fnTallyRecordAdd( l );
   }
   fnCalcTotals();
   fnUpdateStatsGUI();
}


/**
 ** M A I N   P R O G R A M -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 **/
void main(int argc, char *argv[])
{
   ULONG   signals;
   ULONG   ulInputEvent;

   APTR    aboutwin = NULL;
   LONG    lStat;

   BPTR               tmplock;
   struct WBStartup  *WBenchMsg   = NULL;
   struct WBArg      *pWBArg      = NULL;

   char               szProgramSpec[ FMSIZE+1 ];


   MG.running = TRUE;

   //
   // setup variables, read startup params, etc...
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   JMH_Startup( argc, argv );

   //
   // attempt to create window objects and attach to application parent
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if ( fnConstructMainWindow() == FALSE )   {  JMH_Quit( "Failed to create MAIN window." );  }

   //
   // Load application settings; populate global vars
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   DoMethod( MG.App, MUIM_Application_Load, MUIV_Application_Load_ENV );

   //
   // open main window
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fnInitMainWindow();

   //
   // if we're passed a data file, load it
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if ( argc > 1 )
   {
      fnOpen( argv[1] );
fnUpdateAllStats();
   }
   else
   {
      WBenchMsg   = (struct WBStartup *)argv;
      pWBArg      = WBenchMsg->sm_ArgList;

      pWBArg++;   // get first parameter

      if ( pWBArg )
      {
         if ( ( pWBArg->wa_Lock ) && ( *pWBArg->wa_Name ) )
         {
            tmplock  = Lock( pWBArg->wa_Name, ACCESS_READ );
            NameFromLock( tmplock, szProgramSpec, FMSIZE );

            fnOpen( szProgramSpec );
fnUpdateAllStats();

            UnLock( tmplock );
         }
      }
   }

   //
   // show 'em what it's all 'About'
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//   JMH_About();

   //
   //   MAIN LOOP          MAIN LOOP         MAIN LOOP         MAIN LOOP
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   while ( MG.running )
   {
      ulInputEvent = DoMethod( MG.App, MUIM_Application_NewInput, &signals );
      switch ( ulInputEvent )
      {
         case MUIV_Application_ReturnID_Quit:
         case ID_MENU_PROJECT_QUIT:
            get( MG.App, MUIA_Application_ForceQuit, &lStat );
            if ( lStat == TRUE )
            {
               MG.running = FALSE;
            }
            else if ( TRUE == MG.fDataChanged )
            {
               lStat = MUI_Request( MG.App, MG.WIN_MAIN, 0, NULL, "Quit|*Save Changes|Cancel",
                                    "Data has been changed!  Are you sure you want to quit?", NULL );
               switch( lStat )
               {
                  case 1:  // Quit
                     MG.running = FALSE;
                     break;
                  case 2:  // Save Changes then Quit
                     if ( strcmp( MG.szProjectSpec, "" ) == 0 )
                     {
                        JMH_FileReq( MG.WIN_MAIN, "Save issue file", TRUE, FALSE, MG.szProjectSpec, sizeof( MG.szProjectSpec ) );
                     }

                     if ( strcmp( MG.szProjectSpec, "" ) != 0 )
                     {
                        fnSave( MG.szProjectSpec );
                        MG.fDataChanged = FALSE;
                     }

                     MG.running = FALSE;
                     break;
                  case 0:  // cancel
                  default:
                     break;
               }
            }
            else
            {
               // no data has changed -- let's leave...
               MG.running = FALSE;
            }
            break;

         // MENUS ---------------------------------------------
         case ID_MENU_PROJECT_NEW:
            if ( MUI_Request( MG.App, MG.WIN_MAIN, 0, NULL, "OK|*Cancel",
                              "Are you sure you wish to clear all data?", NULL ) == 1 )
            {
               fnClearMainWindow();
fnUpdateAllStats();
            }
            break;
         case ID_MENU_PROJECT_OPEN:
            if ( JMH_FileReq( MG.WIN_MAIN, "Open issue file", FALSE, FALSE, MG.szProjectSpec, sizeof( MG.szProjectSpec ) ) )
            {
               MG.fDataChanged = FALSE;
               fnOpen( MG.szProjectSpec );
               DoMethod( MAIN.DLIS_List, MUIM_List_Sort );
               fnUpdateAllStats();
            }
            break;
         case ID_BUT_MAIN_SAVE:
         case ID_MENU_PROJECT_SAVE:
            if ( strcmp( MG.szProjectSpec, "" ) == 0 )
            {
               JMH_FileReq( MG.WIN_MAIN, "Save issue file", TRUE, FALSE, MG.szProjectSpec, sizeof( MG.szProjectSpec ) );
            }

            if ( strcmp( MG.szProjectSpec, "" ) != 0 )
            {
               fnSave( MG.szProjectSpec );
               MG.fDataChanged = FALSE;
            }
            break;
         case ID_MENU_PROJECT_SAVEAS:
            if ( JMH_FileReq( MG.WIN_MAIN, "Save issue file", TRUE, FALSE, MG.szProjectSpec, sizeof( MG.szProjectSpec ) ) )
            {
               fnSave( MG.szProjectSpec );
               MG.fDataChanged = FALSE;
            }
            break;
         case ID_MENU_PROJECT_ABOUT:
            JMH_About();
            break;
         case ID_MENU_PROJECT_ABOUTMUI:
            if ( !aboutwin )
            {
               aboutwin = AboutmuiObject,
                  MUIA_Window_RefWindow    , MG.WIN_MAIN,
                  MUIA_Aboutmui_Application, MG.App,
                  End;
            }
            if ( aboutwin )
               set( aboutwin, MUIA_Window_Open, TRUE );
            else
               DisplayBeep(0);
            break;
         case ID_MENU_SETTINGS_MUI:
            DoMethod( MG.App, MUIM_Application_OpenConfigWindow, 0L );
            break;

         case ID_BUT_MAIN_NEW:
            DoMethod( MAIN.DLIS_List, MUIM_DataList_AddDefaultRecord, MUIV_DataList_AddRecord_ReplaceNone, MUIV_List_Insert_Sorted );
            get( MAIN.DLIS_List, MUIA_List_InsertPosition, &lStat );
            set( MAIN.DLIS_List, MUIA_List_Active, lStat );
            set( MG.WIN_MAIN, MUIA_Window_ActiveObject, MAIN.STR_Description );
            MG.fDataChanged = TRUE;
fnUpdateAllStats();
            break;

         case ID_BUT_MAIN_DEL:
            if ( MUI_Request( MG.App, MG.WIN_MAIN, 0, NULL, "Delete|*Cancel",
                              "Are you sure you want to delete the selected records?", NULL ) == 1 )
            {
               DoMethod( MAIN.DLIS_List, MUIM_List_Remove, MUIV_List_Remove_Selected );
fnUpdateAllStats();
               MG.fDataChanged = TRUE;
            }
            break;

         case ID_BUT_MAIN_APPLY:
            set( MAIN.DLIS_List, MUIA_List_Quiet, TRUE );
            get( MAIN.DLIS_List, MUIA_List_Active, &lStat );
            DoMethod( MAIN.DLIS_List, MUIM_DataList_AddRecord, MUIV_DataList_AddRecord_ReplaceActive, 0L );
            set( MAIN.DLIS_List, MUIA_List_Active, lStat );
            set( MAIN.DLIS_List, MUIA_List_Quiet, FALSE );
fnUpdateAllStats();
            MG.fDataChanged = TRUE;
            break;

         case ID_EVENT_SORT:
            get( MAIN.MX_PriSort, MUIA_Radio_Active, &lStat );
            set( MAIN.DLIS_List, MUIA_DataList_SortPrimary, lStat );
            get( MAIN.MX_SecSort, MUIA_Radio_Active, &lStat );
            set( MAIN.DLIS_List, MUIA_DataList_SortSecondary, lStat );
            get( MAIN.CHE_Ascending, MUIA_Selected, &lStat );
            if ( lStat )
            {
               set( MAIN.DLIS_List, MUIA_DataList_Sort, MUIV_DataList_Sort_Ascending );
            }
            else
            {
               set( MAIN.DLIS_List, MUIA_DataList_Sort, MUIV_DataList_Sort_Descending );
            }
            DoMethod( MAIN.DLIS_List, MUIM_List_Sort );
            break;

         case ID_EVENT_DOUBLECLICK:
            get( MAIN.LV_Listview, MUIA_Listview_ClickColumn, &lStat );
            if ( lStat == 0 )
            {
               set( MAIN.CYC_Status, MUIA_Cycle_Active, MUIV_Cycle_Active_Next );
               DoMethod( MAIN.DLIS_List, MUIM_DataList_AddRecord, MUIV_DataList_AddRecord_ReplaceActive, 0L );
fnUpdateAllStats();
               MG.fDataChanged = TRUE;
            }
            set( MG.WIN_MAIN, MUIA_Window_ActiveObject, MAIN.STR_Description );
            break;
      }
      if ( MG.running && signals ) Wait(signals);
   }

   set( MG.WIN_MAIN, MUIA_Window_Open, FALSE );
   JMH_Quit( NULL );
}
