//==========================================================================//
//                                  Includes                                //
//==========================================================================//
#include <string.h>     // strupr
#include <stdio.h>      // for sprintf.
#include <locale.h>     // TESTING TESTING


#include "perfmon.h"
#include "init.h"       // external declarations for this file

#include "alert.h"      // for AlertIitializeApplication
#include "command.h"    // for ViewChart
#include "grafdata.h"   // for QuerySaveChart
#include "graph.h"      // for GraphInitializeApplication
#include "legend.h"     // for LegendInitializeApplication
#include "log.h"        // for LogInitializeApplication
#include "intrline.h"   // for ILineInitializeApplication
#include "perfdata.h"   // for PerfDataInitializeInstance
#include "perfmops.h"   // for OpenFileHandler, for now
#include "status.h"     // for StatusInitializeApplication
#include "timeline.h"   // for TLineInitializeApplication
#include "playback.h"   // for PlaybackInitializeInstance
#include "registry.h"   // for Load/SaveMainWindowPlacement
#include "report.h"     // for ReportInitializeApplication
#include "toolbar.h"    // for ToolbarInitializeApplication
#include "utils.h"
#include "fileopen.h"   // for FileOpen
#include "pmemory.h"    // for MemoryFree

extern   TCHAR          DefaultLangId[] ;
extern   TCHAR          EnglishLangId[] ;

//==========================================================================//
//                                  Constants                               //
//==========================================================================//


#define szPerfmonMainClass TEXT("PerfmonMainClass")

HHOOK   lpMsgFilterProc ;
DWORD FAR PASCAL MessageFilterProc (int nCode, WPARAM wParam,
      LPARAM lParam) ;


//==========================================================================//
//                              Local Functions                             //
//==========================================================================//


void GetScalesFonts (void)
   {
   LOGFONT        lf ;

   memset (&lf, 0, sizeof (lf)) ;

   lstrcpy (lf.lfFaceName, szScalesFontFace) ;
   lf.lfHeight = iScalesFontHeight ;
   lf.lfWeight = FW_REGULAR ;

   hFontScales = CreateFontIndirect (&lf) ;

   lf.lfWeight = FW_BOLD ;
   hFontScalesBold = CreateFontIndirect (&lf) ;
   }


BOOL InitializeSystemValues (void)
/*
   Effect:        Read and store in variables the various system values,
                  such as the width and height of the screen and icons,
                  the width of scroll bars, etc.

   Called By:     PerfmonInitialize only.

   Returns:       Whether this function was successful in getting all
                  needed system values.
*/
   {  // InitializeSystemValues
   xScreenWidth =  GetSystemMetrics (SM_CXSCREEN) ;
   yScreenHeight = GetSystemMetrics (SM_CYSCREEN) ;

   xBorderWidth = GetSystemMetrics (SM_CXBORDER) ;
   yBorderHeight = GetSystemMetrics (SM_CYBORDER) ;

   xScrollWidth = GetSystemMetrics (SM_CXVSCROLL) ;
   yScrollHeight = GetSystemMetrics (SM_CYHSCROLL) ;

   xScrollThumbWidth = GetSystemMetrics (SM_CXHTHUMB) ;
   yScrollThumbHeight = GetSystemMetrics (SM_CYVTHUMB) ;

   xDlgBorderWidth = GetSystemMetrics (SM_CXDLGFRAME) ;
   yDlgBorderHeight = GetSystemMetrics (SM_CYDLGFRAME) ;

   MinimumSize = yScrollHeight +
                 GetSystemMetrics (SM_CYMENU) +
                 GetSystemMetrics (SM_CYCAPTION) ;

   //================================================================//
   // create all the brushes and pens for performance improvement    //
   //================================================================//
   CreatePerfmonSystemObjects () ;
   hWhitePen = CreatePen (PS_SOLID, 3, crWhite) ;


// TESTING TESTING TESTING
#if 0
   {
   DWORD GDIBatchLimit = GdiSetBatchLimit (1) ;
   }
//mike1(TEXT("SetLocale returns %s"), setlocale(LC_NUMERIC, NULL));
mike1(TEXT("SetLocale returns %s"), setlocale(LC_NUMERIC, NULL));
#endif


   return (TRUE) ;
   }  // InitializeSystemValues


BOOL InitializeApplication (void)
/*
   Effect:        Perform all initializations required for the FIRST
                  instance of the Perfmon application. In particular,
                  register all of Perfmon's window classes.

   Note:          There is no background brush set for the MainWindow
                  class so that the main window is never erased. The
                  client area of MainWindow is always covered by one
                  of the view windows. If we erase it, it would just
                  flicker needlessly.

   Called By:     PerfmonInitialize only.

   Returns:       Whether this function was successful in initializing.
*/
   {  // InitializeApplication
   BOOL           bSuccess ;
   WNDCLASS       wc ;
   TCHAR          LocalHelpFileName [ShortTextLen] ;
   LPTSTR         pFileName ;

   hIcon = LoadIcon (hInstance, idIcon) ;

   //=============================//
   // Register Main window class  //
   //=============================//

   wc.style         = CS_DBLCLKS | CS_BYTEALIGNCLIENT;
   wc.lpfnWndProc   = (WNDPROC) MainWndProc;
   wc.hInstance     = hInstance;
   wc.cbClsExtra    = 0 ;
   wc.cbWndExtra    = 0;
   wc.hIcon         = hIcon ;
   wc.hCursor       = LoadCursor(NULL, IDI_APPLICATION);
   wc.hbrBackground = NULL ;                             // see note above
   wc.lpszMenuName  = idMenuChart ;
   wc.lpszClassName = szPerfmonMainClass ;

   bSuccess = RegisterClass (&wc) ;

   //=============================//
   // Register Abstract "Systems" //
   //=============================//
   hbLightGray = GetStockObject (LTGRAY_BRUSH) ;

   if (bSuccess)
      bSuccess = StatusInitializeApplication () ;

   if (bSuccess)
      bSuccess = GraphInitializeApplication () ;

#ifdef ADVANCED_PERFMON
   if (bSuccess)
      bSuccess = LogInitializeApplication () ;

   if (bSuccess)
      bSuccess = AlertInitializeApplication () ;

   if (bSuccess)
      bSuccess = ReportInitializeApplication () ;

   if (bSuccess)
      bSuccess = ILineInitializeApplication () ;

   if (bSuccess)
      bSuccess = TLineInitializeApplication () ;
#endif

   // setup messagehook to handle F1 as help
   lpMsgFilterProc = SetWindowsHookEx (WH_MSGFILTER,
          (HOOKPROC) MessageFilterProc,
          hInstance,
          GetCurrentThreadId()) ;

   // get the help file full path name
   LoadString (hInstance, IDS_HELPFILE_NAME,
      (LPTSTR)LocalHelpFileName, ShortTextLen-1);


   if (LocalHelpFileName[0])
      {
      pszHelpFile = (LPTSTR) MemoryAllocate (FilePathLen * sizeof (TCHAR)) ;
      SearchPath (NULL, LocalHelpFileName, NULL,
            FilePathLen - 1, pszHelpFile, &pFileName) ;
      }
   else
      {
      // no help file
      pszHelpFile = (LPTSTR) MemoryAllocate (sizeof (TCHAR)) ;
      *pszHelpFile = TEXT('\0') ;
      }

   return (bSuccess) ;
   }  // InitializeApplication



BOOL InitializeInstance (int nCmdShow, LPCSTR lpszCmdLine)
/*
   Effect:        Perform all initializations required for EACH instance
                  of the Perfmon application. In particular, create all
                  of Perfmon's initial windows, and perform any other
                  initializations except registering classes (done in
                  InitializeApplication).

   Called By:     PerfmonInitialize only.

   Note:          This function has multiple return points.

   Returns:       Whether this function was successful in initalizing.
*/
   {  // InitializeInstance
   DWORD          ComputerNameLength;
   TCHAR          szApplication [WindowCaptionLen] ;


   //=============================//
   // Set Priority high           //
   //=============================//

   SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS) ;
   SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST) ;

   //=============================//
   // Load Resources              //
   //=============================//

   GetScalesFonts () ;

   hMenuChart = LoadMenu (hInstance, idMenuChart) ;

#ifdef ADVANCED_PERFMON
   hMenuAlert = LoadMenu (hInstance, idMenuAlert) ;
   hMenuLog = LoadMenu (hInstance, idMenuLog) ;
   hMenuReport = LoadMenu (hInstance, idMenuReport) ;
#endif

   hAccelerators = LoadAccelerators (hInstance, idAccelerators) ;


   //=============================//
   // Initialize Systems          //
   //=============================//

   iLanguage = GetUserDefaultLangID() ;
   iEnglishLanguage = MAKELANGID (LANG_ENGLISH, LANG_NEUTRAL) ;
//   iEnglishLanguage = MAKELANGID (iLanguage & 0x0ff, LANG_NEUTRAL) ;
   TSPRINTF (DefaultLangId, TEXT("%03x"), iLanguage) ;
   TSPRINTF (EnglishLangId, TEXT("%03x"), iEnglishLanguage) ;

   // GetComputerName returns the name without the "\\" prefix. We add
   // the prefix before even calling the routine. This is so that all our
   // computer names have the prefix and are therefore compatible with
   // I_SetSystemFocus (see perfmops.c).

   ComputerNameLength = MAX_COMPUTERNAME_LENGTH + 1;
   lstrcpy (LocalComputerName, szComputerPrefix) ;
   GetComputerName (LocalComputerName + lstrlen (szComputerPrefix), 
                    &ComputerNameLength);

   PlaybackInitializeInstance () ;
   PerfDataInitializeInstance () ;

   //=============================//
   // Create Window               //
   //=============================//

   StringLoad (IDS_APPNAME, szApplication) ;
   hWndMain = CreateWindow (szPerfmonMainClass,
                            szApplication,
  	                    	    WS_OVERLAPPEDWINDOW | WS_BORDER,
                     		 CW_USEDEFAULT, CW_USEDEFAULT, 
                     		 CW_USEDEFAULT, CW_USEDEFAULT, 
		                      NULL,
                            NULL,
                            NULL,
                            NULL);

   if (!hWndMain)
      return (FALSE) ;

   ViewChart (hWndMain) ;

   LoadMainWindowPlacement (hWndMain) ;

   return (TRUE) ;
   }  // InitializeInstance


//==========================================================================//
//                             Exported Functions                           //
//==========================================================================//


BOOL PerfmonInitialize (HINSTANCE hCurrentInstance,
                        HINSTANCE hPrevInstance,
                        LPCSTR lpszCmdLine,
                        int nCmdShow)
/*
   Effect:        Performa all initializations required when Perfmon is
                  started. In particular, initialize all "systems", register
                  all window classes, create needed windows, read in and
                  process font and Perfmon lists.

   Called By:     WinMain only, at the start of the application.

   Assert:        There are no other instances of Perfmon currently
                  executing.

   Returns:       Whether initialization was successful. If this function
                  returns FALSE, Perfmon should exit immediately.

   Internals:     The bSuccess variable is used to conditionalize each
                  successive initialization step.
*/
   {  // PerfmonInitialize
   BOOL           bSuccess ;
   TCHAR          szFilePath [FilePathLen + 1] ;
   LPTSTR         pFileNameStart ;
   HANDLE         hFindFile ;
   WIN32_FIND_DATA FindFileInfo ;
   CHAR           QuoteChar ;
   LPSTR          pCmdLine ;
   int            NameOffset ;


   hInstance = hCurrentInstance ;
   bSuccess = InitializeSystemValues () ;

   if (bSuccess && !hPrevInstance)
      bSuccess = InitializeApplication () ;

   if (bSuccess)
      bSuccess = InitializeInstance (nCmdShow, lpszCmdLine) ;

   GetDateTimeFormats() ;

   if (bSuccess)
      {

      if (strempty (lpszCmdLine))
         StringLoad (IDS_DEFAULTPATH, szFilePath) ;
      else
         {
         // check for single or double quote
         QuoteChar = *lpszCmdLine ;
         if (QuoteChar == '\'' || QuoteChar == '\"')
            {
            lpszCmdLine++ ;

            // remove the matching QuoteChar if found
            pCmdLine = (LPSTR) lpszCmdLine ;
            while (*pCmdLine != '\0')
               {
               if (*pCmdLine == QuoteChar)
                  {
                  *pCmdLine = '\0' ;
                  break ;
                  }
               else
                  {
                  pCmdLine++ ;
                  }
               }
            }

         // convert the LPSTR to LPTSTR

         mbstowcs (szFilePath, lpszCmdLine, strlen(lpszCmdLine) + 1) ;

         pFileNameStart = ExtractFileName (szFilePath) ;
         NameOffset = pFileNameStart - szFilePath ;

         // convert short filename to long NTFS filename if necessary
         hFindFile = FindFirstFile (szFilePath, &FindFileInfo) ;
         if (hFindFile && hFindFile != INVALID_HANDLE_VALUE)
            {
            // append the file name back to the path name
            lstrcpy (&szFilePath[NameOffset], FindFileInfo.cFileName) ;
            FindClose (hFindFile) ;
            }
         }
      
//      OpenFileHandler (hWndMain, szFilePath) ;
      FileOpen (hWndMain, (int)0, (LPTSTR)szFilePath) ;
      PrepareMenu (GetMenu (hWndMain));
      }

   return (bSuccess) ;
   }  // PerfmonInitialize



void PerfmonClose (HWND hWndMain)
   {
   if (!QuerySaveChart (hWndMain, pGraphs))
      return ;

   // close the log file for now.
   // need to query the user later..!!
   if (LogCollecting (hWndLog))
      {
      PLOG pLog = LogData (hWndLog) ;
      
      if (pLog)
         {
         CloseLog (hWndLog, pLog) ;
         }
      }
      

   // free all the filenames
   if (pChartFullFileName)
      {
      MemoryFree (pChartFullFileName) ;
      pChartFullFileName = NULL ;
      }
   if (pAlertFullFileName)
      {
      MemoryFree (pAlertFullFileName) ;
      pAlertFullFileName = NULL ;
      }
   if (pLogFullFileName)
      {
      MemoryFree (pLogFullFileName) ;
      pLogFullFileName = NULL ;
      }
   if (pReportFullFileName)
      {
      MemoryFree (pReportFullFileName) ;
      pReportFullFileName = NULL ;
      }

   // free all the GDI resources
   DeletePen (hWhitePen) ;
   DeletePerfmonSystemObjects () ;

   SaveMainWindowPlacement (hWndMain) ;
   DestroyWindow (hWndMain) ;
   }  // PerfmonClose


