#include <windows.h>
#include <commctrl.h>
#include <math.h>

#include "base/at_error.h"
#include "drs/drs_progress.h"
#include "drs/dll_entry.h"

//From dlgsort.rc
#define IDC_ProgressBar	101
#define IDI_Icon	1
#define IDC_TextPercent	103
#define IDC_TextPrompt	102
#define IDD_Progress	1
#define IDD_ProgressLong	2

//ProgressBar window messages from commctrl.h
//#define PBM_SETRANGE            (WM_USER+1)   ;Default = 0..100
//#define PBM_SETPOS              (WM_USER+2)
//#define PBM_DELTAPOS            (WM_USER+3)
//#define PBM_SETSTEP             (WM_USER+4)
//#define PBM_STEPIT              (WM_USER+5)

//Dialog window routine
BOOL CALLBACK DlgProgress( HWND hDlg, UINT message, UINT wParam, LONG lParam)
{
  switch( message)
    {
    case WM_INITDIALOG:
      #ifdef WIN16
      #else
      SendDlgItemMessage( hDlg, IDC_ProgressBar, PBM_SETRANGE, (WPARAM) 0, MAKELPARAM( 0, 100));
      SendDlgItemMessage( hDlg, IDC_ProgressBar, PBM_SETPOS, (WPARAM) 0, 0);
      //SendDlgItemMessage( hDlg, IDC_TextPercent, WM_SETTEXT, 0, MAKELPARAM(""));
      #endif
      return true;
    case WM_COMMAND:
      switch( LOWORD(wParam)) //Loword is control id
      {
        case IDCANCEL:
          if( HIWORD(wParam) == BN_CLICKED) //Hi word is notification mesage
             * (bool *) GetWindowLong( hDlg, GWL_USERDATA) = true;
          break;
       }
    }
  return false;
}

DRS_Progress::DRS_Progress( byte *sTitle, byte const *sPrompt, bool isLongProcess, bool isAllowCancel)
      : isCancel( false), hDialog(0), pPrompt( sPrompt)
{

  InitCommonControls();

  #ifdef WIN16
    FARPROC fpDialog = MakeProcInstance( (FARPROC)DlgProgress, hMod);
    hDialog = CreateDialog( hMod, MAKEINTRESOURCE(1), NULL, fpDialog);
  #else
    //Obsolete with hInst storage
    //HMODULE hMod = GetModuleHandle( "at_drs32.dll"); //Win32 ONLY
    AT_Assert( hInst, *this, "Module instance");
    hDialog = CreateDialog( hInst,
                 MAKEINTRESOURCE( isLongProcess? IDD_ProgressLong : IDD_Progress),
                 HWND_DESKTOP, (DLGPROC) DlgProgress);
    #ifndef NDEBUG
    AT_Assert( hDialog, *this, "Create dialog");
    #endif
  #endif

  if( !hDialog) return;

  //Center dialog on screen, DS_CENTER bug in Borland!!
  RECT oRect;
  if( GetWindowRect( hDialog, (LPRECT) &oRect))
    {
    GetSystemMetrics( SM_CXSCREEN);
    GetSystemMetrics( SM_CYSCREEN);
    MoveWindow( hDialog, (GetSystemMetrics( SM_CXSCREEN) - (oRect.right - oRect.left)) / 2,
                         (GetSystemMetrics( SM_CYSCREEN) - (oRect.bottom - oRect.top)) / 2,
                         oRect.right - oRect.left,
                         oRect.bottom - oRect.top, true);
    }

  //Set address of isCancel in Window.
  //Win32 only!!!
  SetWindowLong( hDialog, GWL_USERDATA, (LPARAM) &isCancel);

  //Set window title
  if( sTitle) SetWindowTextA( hDialog, (LPCSTR) sTitle);

  //Set prompt
  if( sPrompt) SendDlgItemMessage( hDialog, IDC_TextPrompt, WM_SETTEXT, 0, (LPARAM)sPrompt);

  if( !isAllowCancel)
    ShowWindow( GetDlgItem( hDialog, IDCANCEL), SW_HIDE);

  ShowWindow( hDialog, SW_SHOW);
}

DRS_Progress::~DRS_Progress()
{
  if( hDialog)
    DestroyWindow( hDialog);
}

bool DRS_Progress::progress( uint32 lCurVal, uint32 lTotalVal)
{

    if( lTotalVal)
      SendDlgItemMessage( hDialog, IDC_ProgressBar, PBM_SETPOS, (WPARAM) ((lCurVal * 100) / lTotalVal), (LPARAM) 0);

    ProcessMessages();
return !isCancel;
}

void DRS_Progress::ProcessMessages() const
{
  // Assure dialog window and control updates.

    MSG msg;
    while( PeekMessage( &msg, 0,0,0, PM_REMOVE))
      {
      if( ! hDialog || !IsDialogMessage( hDialog, &msg) )
        {
        TranslateMessage( &msg);
        DispatchMessage( &msg);
        }
      }
}

bool DRS_ProgressLong::progress( uint32 lCurVal, uint32 lTotalVal)
{

  if( (lCurVal % ProcInterval) == 0 || (lCurVal == lTotalVal))
    {
    byte buf[256];
    wsprintfA( (LPSTR) buf, "%s %u / %u", pPrompt, lCurVal, lTotalVal);
    SendDlgItemMessage( hDialog, IDC_TextPrompt, WM_SETTEXT, 0, (LPARAM)buf);

    return DRS_Progress::progress( lCurVal, lTotalVal);
    }
return !isCancel;    
}

