// ProgressDialog2.h

#ifndef __PROGRESS_DIALOG_2_H
#define __PROGRESS_DIALOG_2_H

#include "../../../Common/MyCom.h"

#include "../../../Windows/ErrorMsg.h"
#include "../../../Windows/Synchronization.h"
#include "../../../Windows/Thread.h"

#include "../../../Windows/Control/Dialog.h"
#include "../../../Windows/Control/ListView.h"
#include "../../../Windows/Control/ProgressBar.h"

#include "MyWindowsNew.h"

struct CProgressMessageBoxPair
{
  UString Title;
  UString Message;
};

struct CProgressFinalMessage
{
  CProgressMessageBoxPair ErrorMessage;
  CProgressMessageBoxPair OkMessage;

  bool ThereIsMessage() const { return !ErrorMessage.Message.IsEmpty() || !OkMessage.Message.IsEmpty(); }
};

class CProgressSync
{
  bool _stopped;
  bool _paused;

public:
  bool _bytesProgressMode;
  UInt64 _totalBytes;
  UInt64 _completedBytes;
  UInt64 _totalFiles;
  UInt64 _curFiles;
  UInt64 _inSize;
  UInt64 _outSize;
  
  UString _titleFileName;
  UString _status;
  UString _filePath;
  bool _isDir;

  UStringVector Messages;
  CProgressFinalMessage FinalMessage;

  NWindows::NSynchronization::CCriticalSection _cs;

  CProgressSync();

  bool Get_Stopped()
  {
    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
    return _stopped;
  }
  void Set_Stopped(bool val)
  {
    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
    _stopped = val;
  }
  
  bool Get_Paused();
  void Set_Paused(bool val)
  {
    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
    _paused = val;
  }
  
  void Set_BytesProgressMode(bool bytesProgressMode)
  {
    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
    _bytesProgressMode = bytesProgressMode;
  }
  
  HRESULT CheckStop();
  HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const UString &fileName, bool isDir = false);

  void Set_NumFilesTotal(UInt64 val);
  void Set_NumBytesTotal(UInt64 val);
  void Set_NumFilesCur(UInt64 val);
  HRESULT Set_NumBytesCur(const UInt64 *val);
  HRESULT Set_NumBytesCur(UInt64 val);
  void Set_Ratio(const UInt64 *inSize, const UInt64 *outSize);

  void Set_TitleFileName(const UString &fileName);
  void Set_Status(const UString &s);
  void Set_FilePath(const UString &path, bool isDir = false);

  void AddError_Message(const wchar_t *message);
  void AddError_Message_Name(const wchar_t *message, const wchar_t *name);
  void AddError_Code_Name(DWORD systemError, const wchar_t *name);

  bool ThereIsMessage() const { return !Messages.IsEmpty() || FinalMessage.ThereIsMessage(); }
};

class CProgressDialog: public NWindows::NControl::CModalDialog
{
  UString _titleFileName;
  UString _filePath;
  UString _status;
  bool _isDir;

  UString _background_String;
  UString _backgrounded_String;
  UString _foreground_String;
  UString _pause_String;
  UString _continue_String;
  UString _paused_String;

  int _buttonSizeX;
  int _buttonSizeY;

  UINT_PTR _timer;

  UString _title;

  class CU64ToI32Converter
  {
    unsigned _numShiftBits;
    UInt64 _range;
  public:
    CU64ToI32Converter(): _numShiftBits(0), _range(1) {}
    void Init(UInt64 range)
    {
      _range = range;
      // Windows CE doesn't like big number for ProgressBar.
      for (_numShiftBits = 0; range >= ((UInt32)1 << 15); _numShiftBits++)
        range >>= 1;
    }
    int Count(UInt64 val)
    {
      int res = (int)(val >> _numShiftBits);
      if (val == _range)
        res++;
      return res;
    }
  };
  
  CU64ToI32Converter _progressConv;
  UInt64 _progressBar_Pos;
  UInt64 _progressBar_Range;
  
  NWindows::NControl::CProgressBar m_ProgressBar;
  NWindows::NControl::CListView _messageList;
  
  int _numMessages;

  #ifdef __ITaskbarList3_INTERFACE_DEFINED__
  CMyComPtr<ITaskbarList3> _taskbarList;
  #endif
  HWND _hwndForTaskbar;

  UInt32 _prevTime;
  UInt64 _elapsedTime;

  UInt64 _prevPercentValue;
  UInt64 _prevElapsedSec;
  UInt64 _prevRemainingSec;

  UInt64 _totalBytes_Prev;
  UInt64 _processed_Prev;
  UInt64 _packed_Prev;
  UInt64 _ratio_Prev;
  UString _filesStr_Prev;

  unsigned _prevSpeed_MoveBits;
  UInt64 _prevSpeed;

  bool _foreground;

  unsigned _numReduceSymbols;

  bool _wasCreated;
  bool _needClose;

  unsigned _numPostedMessages;
  UInt32 _numAutoSizeMessages;

  bool _errorsWereDisplayed;

  bool _waitCloseByCancelButton;
  bool _cancelWasPressed;
  
  bool _inCancelMessageBox;
  bool _externalCloseMessageWasReceived;


  #ifdef __ITaskbarList3_INTERFACE_DEFINED__
  void SetTaskbarProgressState(TBPFLAG tbpFlags)
  {
    if (_taskbarList && _hwndForTaskbar)
      _taskbarList->SetProgressState(_hwndForTaskbar, tbpFlags);
  }
  #endif
  void SetTaskbarProgressState();

  void UpdateStatInfo(bool showAll);
  bool OnTimer(WPARAM timerID, LPARAM callback);
  void SetProgressRange(UInt64 range);
  void SetProgressPos(UInt64 pos);
  virtual bool OnInit();
  virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
  virtual void OnCancel();
  virtual void OnOK();
  NWindows::NSynchronization::CManualResetEvent _createDialogEvent;
  NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent;
  #ifndef _SFX
  void AddToTitle(LPCWSTR string);
  #endif

  void SetPauseText();
  void SetPriorityText();
  void OnPauseButton();
  void OnPriorityButton();
  bool OnButtonClicked(int buttonID, HWND buttonHWND);
  bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);

  void SetTitleText();
  void ShowSize(int id, UInt64 val, UInt64 &prev);

  void UpdateMessagesDialog();

  void AddMessageDirect(LPCWSTR message, bool needNumber);
  void AddMessage(LPCWSTR message);

  bool OnExternalCloseMessage();
  void EnableErrorsControls(bool enable);

  void ShowAfterMessages(HWND wndParent);

  void CheckNeedClose();
public:
  CProgressSync Sync;
  bool CompressingMode;
  bool WaitMode;
  bool ShowCompressionInfo;
  bool MessagesDisplayed; // = true if user pressed OK on all messages or there are no messages.
  int IconID;

  HWND MainWindow;
  #ifndef _SFX
  UString MainTitle;
  UString MainAddTitle;
  ~CProgressDialog();
  #endif

  CProgressDialog();
  void WaitCreating()
  {
    _createDialogEvent.Set();
    _dialogCreatedEvent.Lock();
  }

  INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = 0);

  void ProcessWasFinished();
};


class CProgressCloser
{
  CProgressDialog *_p;
public:
  CProgressCloser(CProgressDialog &p) : _p(&p) {}
  ~CProgressCloser() { _p->ProcessWasFinished(); }
};

class CProgressThreadVirt
{
  FString ErrorPath1;
  FString ErrorPath2;
protected:
  CProgressFinalMessage FinalMessage;

  // error if any of HRESULT, ErrorMessage, ErrorPath
  virtual HRESULT ProcessVirt() = 0;
  void Process();
public:
  HRESULT Result;
  bool ThreadFinishedOK; // if there is no fatal exception
  CProgressDialog ProgressDialog;

  static THREAD_FUNC_DECL MyThreadFunction(void *param)
  {
    CProgressThreadVirt *p = (CProgressThreadVirt *)param;
    try
    {
      p->Process();
      p->ThreadFinishedOK = true;
    }
    catch (...) { p->Result = E_FAIL; }
    return 0;
  }

  void SetErrorPath1(const FString &path) { ErrorPath1 = path; }
  void SetErrorPath2(const FString &path) { ErrorPath2 = path; }

  HRESULT Create(const UString &title, HWND parentWindow = 0);
  CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {}

  CProgressMessageBoxPair &GetMessagePair(bool isError) { return isError ? FinalMessage.ErrorMessage : FinalMessage.OkMessage; }

};

UString HResultToMessage(HRESULT errorCode);

#endif
