// Copyright 2016 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#ifndef XFA_FWL_CORE_CFWL_MESSAGE_H_
#define XFA_FWL_CORE_CFWL_MESSAGE_H_

#include "core/fxcrt/include/fx_string.h"
#include "core/fxcrt/include/fx_system.h"
#include "xfa/fwl/core/fwl_error.h"

enum class CFWL_MessageType {
  None = 0,

  Activate,
  Close,
  Cursor,
  Deactivate,
  DropFiles,
  Key,
  KillFocus,
  Mouse,
  MouseWheel,
  Post,
  SetFocus,
  Size,
  TaskClicked,
  WindowMove,
  WindowWillMove
};

enum class FWL_MouseCommand {
  LeftButtonDown,
  LeftButtonUp,
  LeftButtonDblClk,
  RightButtonDown,
  RightButtonUp,
  RightButtonDblClk,
  MiddleButtonDown,
  MiddleButtonUp,
  MiddleButtonDblClk,
  Move,
  Enter,
  Leave,
  Hover
};

enum class FWL_KeyCommand { KeyDown, KeyUp, Char };

class IFWL_Widget;

class CFWL_Message {
 public:
  CFWL_Message()
      : m_pSrcTarget(nullptr),
        m_pDstTarget(nullptr),
        m_dwExtend(0),
        m_dwRefCount(1) {}
  virtual ~CFWL_Message() {}

  virtual CFWL_Message* Clone() { return nullptr; }
  virtual FWL_Error GetClassName(CFX_WideString& wsClass) const {
    return FWL_Error::Succeeded;
  }
  virtual CFWL_MessageType GetClassID() const { return CFWL_MessageType::None; }

  uint32_t Release() {
    m_dwRefCount--;
    uint32_t dwRefCount = m_dwRefCount;
    if (!m_dwRefCount)
      delete this;
    return dwRefCount;
  }

  CFWL_Message* Retain() {
    m_dwRefCount++;
    return this;
  }

  IFWL_Widget* m_pSrcTarget;
  IFWL_Widget* m_pDstTarget;
  uint32_t m_dwExtend;

 private:
  uint32_t m_dwRefCount;
};

#define BEGIN_FWL_MESSAGE_DEF(classname, msgType)                    \
  class classname : public CFWL_Message {                            \
   public:                                                           \
    classname() : CFWL_Message() {}                                  \
    CFWL_Message* Clone() override { return new classname(*this); }  \
    FWL_Error GetClassName(CFX_WideString& wsClass) const override { \
      wsClass = L## #classname;                                      \
      return FWL_Error::Succeeded;                                   \
    }                                                                \
    CFWL_MessageType GetClassID() const override { return msgType; }

#define END_FWL_MESSAGE_DEF \
  }                         \
  ;  // NOLINT

BEGIN_FWL_MESSAGE_DEF(CFWL_MsgActivate, CFWL_MessageType::Activate)
END_FWL_MESSAGE_DEF

BEGIN_FWL_MESSAGE_DEF(CFWL_MsgDeactivate, CFWL_MessageType::Deactivate)
END_FWL_MESSAGE_DEF

BEGIN_FWL_MESSAGE_DEF(CFWL_MsgMouse, CFWL_MessageType::Mouse)
FX_FLOAT m_fx;
FX_FLOAT m_fy;
uint32_t m_dwFlags;
FWL_MouseCommand m_dwCmd;
END_FWL_MESSAGE_DEF

BEGIN_FWL_MESSAGE_DEF(CFWL_MsgMouseWheel, CFWL_MessageType::MouseWheel)
FX_FLOAT m_fx;
FX_FLOAT m_fy;
FX_FLOAT m_fDeltaX;
FX_FLOAT m_fDeltaY;
uint32_t m_dwFlags;
END_FWL_MESSAGE_DEF

BEGIN_FWL_MESSAGE_DEF(CFWL_MsgSetFocus, CFWL_MessageType::SetFocus)
IFWL_Widget* m_pKillFocus;
END_FWL_MESSAGE_DEF

BEGIN_FWL_MESSAGE_DEF(CFWL_MsgKillFocus, CFWL_MessageType::KillFocus)
IFWL_Widget* m_pSetFocus;
END_FWL_MESSAGE_DEF

BEGIN_FWL_MESSAGE_DEF(CFWL_MsgKey, CFWL_MessageType::Key)
uint32_t m_dwKeyCode;
uint32_t m_dwFlags;
FWL_KeyCommand m_dwCmd;
END_FWL_MESSAGE_DEF

BEGIN_FWL_MESSAGE_DEF(CFWL_MsgCursor, CFWL_MessageType::Cursor)
END_FWL_MESSAGE_DEF

BEGIN_FWL_MESSAGE_DEF(CFWL_MsgSize, CFWL_MessageType::Size)
int32_t m_iWidth;
int32_t m_iHeight;
END_FWL_MESSAGE_DEF

BEGIN_FWL_MESSAGE_DEF(CFWL_MsgWindowMove, CFWL_MessageType::WindowMove)
FX_FLOAT m_fx;
FX_FLOAT m_fy;
END_FWL_MESSAGE_DEF

BEGIN_FWL_MESSAGE_DEF(CFWL_MsgDropFiles, CFWL_MessageType::DropFiles)
CFWL_MsgDropFiles(const CFWL_MsgDropFiles& copy) {
  m_pDstTarget = copy.m_pDstTarget;
  m_pSrcTarget = copy.m_pSrcTarget;
  m_fx = copy.m_fx;
  m_fy = copy.m_fy;
  m_files.Append(copy.m_files);
}
FX_FLOAT m_fx;
FX_FLOAT m_fy;
CFX_WideStringArray m_files;
END_FWL_MESSAGE_DEF

BEGIN_FWL_MESSAGE_DEF(CFWL_MsgTaskClicked, CFWL_MessageType::TaskClicked)
FX_FLOAT m_fx;
FX_FLOAT m_fy;
END_FWL_MESSAGE_DEF

BEGIN_FWL_MESSAGE_DEF(CFWL_MsgClose, CFWL_MessageType::Close)
END_FWL_MESSAGE_DEF

BEGIN_FWL_MESSAGE_DEF(CFWL_MsgWindowWillMove, CFWL_MessageType::WindowWillMove)
END_FWL_MESSAGE_DEF

#endif  // XFA_FWL_CORE_CFWL_MESSAGE_H_