// Copyright 2014 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_SRC_FWL_CORE_FWL_GRIDIMP_H_
#define XFA_SRC_FWL_CORE_FWL_GRIDIMP_H_

#include "xfa/include/fwl/core/fwl_app.h"
#include "xfa/include/fwl/core/fwl_content.h"
#include "xfa/include/fwl/core/fwl_grid.h"
#include "xfa/src/fwl/core/fwl_contentimp.h"

class CFWL_GridLength {
 public:
  CFWL_GridLength() : fLength(0), eUnit(FWL_GRIDUNIT_Fixed) {}
  CFWL_GridLength(FX_FLOAT fValue, FWL_GRIDUNIT e)
      : fLength(fValue), eUnit(e) {}
  FX_FLOAT fLength;
  FWL_GRIDUNIT eUnit;
};

class CFWL_GridColRow {
 public:
  CFWL_GridColRow()
      : m_Size(1, FWL_GRIDUNIT_Scaled),
        m_MinSize(0, FWL_GRIDUNIT_Fixed),
        m_MaxSize(0, FWL_GRIDUNIT_Infinity),
        m_fActualSize(0),
        m_fActualPos(0) {}
  CFWL_GridLength m_Size;
  CFWL_GridLength m_MinSize;
  CFWL_GridLength m_MaxSize;
  FX_FLOAT m_fActualSize;
  FX_FLOAT m_fActualPos;
};

class CFWL_GridWidgetInfo {
 public:
  CFWL_GridWidgetInfo()
      : m_iColumn(0),
        m_iColumnSpan(1),
        m_iRow(0),
        m_iRowSpan(1),
        m_dwMarginFlag(0),
        m_fActualWidth(0),
        m_fActualHeight(0) {
    m_Size[FWL_GRIDSIZE_Width].eUnit = FWL_GRIDUNIT_Auto;
    m_Size[FWL_GRIDSIZE_Width].fLength = 0;
    m_Size[FWL_GRIDSIZE_Height].eUnit = FWL_GRIDUNIT_Auto;
    m_Size[FWL_GRIDSIZE_Height].fLength = 0;
    m_Size[FWL_GRIDSIZE_MinWidth].eUnit = FWL_GRIDUNIT_Fixed;
    m_Size[FWL_GRIDSIZE_MinWidth].fLength = 0;
    m_Size[FWL_GRIDSIZE_MaxWidth].eUnit = FWL_GRIDUNIT_Infinity;
    m_Size[FWL_GRIDSIZE_MaxWidth].fLength = 0;
    m_Size[FWL_GRIDSIZE_MinHeight].eUnit = FWL_GRIDUNIT_Fixed;
    m_Size[FWL_GRIDSIZE_MinHeight].fLength = 0;
    m_Size[FWL_GRIDSIZE_MaxHeight].eUnit = FWL_GRIDUNIT_Infinity;
    m_Size[FWL_GRIDSIZE_MaxHeight].fLength = 0;
    m_Margin[0] = m_Margin[1] = m_Margin[2] = m_Margin[3] = 0;
  }
  int32_t m_iColumn;
  int32_t m_iColumnSpan;
  int32_t m_iRow;
  int32_t m_iRowSpan;
  CFWL_GridLength m_Size[6];
  FX_DWORD m_dwMarginFlag;
  FX_FLOAT m_Margin[4];
  FX_FLOAT m_fActualWidth;
  FX_FLOAT m_fActualHeight;
};

class CFWL_GridImp : public CFWL_ContentImp {
 public:
  CFWL_GridImp(const CFWL_WidgetImpProperties& properties, IFWL_Widget* pOuter);
  virtual ~CFWL_GridImp();
  virtual FWL_ERR GetClassName(CFX_WideString& wsClass) const;
  virtual FX_DWORD GetClassID() const;
  virtual FWL_ERR Initialize();
  virtual FWL_ERR Finalize();
  virtual FWL_ERR GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize = FALSE);
  virtual FWL_ERR SetWidgetRect(const CFX_RectF& rect);
  virtual FWL_ERR Update();
  virtual FWL_ERR DrawWidget(CFX_Graphics* pGraphics,
                             const CFX_Matrix* pMatrix = NULL);

  virtual FWL_ERR InsertWidget(IFWL_Widget* pChild, int32_t nIndex = -1);
  virtual FWL_ERR RemoveWidget(IFWL_Widget* pWidget);
  virtual FWL_HGRIDCOLROW InsertColRow(FX_BOOL bColumn, int32_t nIndex = -1);
  virtual int32_t CountColRows(FX_BOOL bColumn);
  virtual FWL_HGRIDCOLROW GetColRow(FX_BOOL bColumn, int32_t nIndex);
  virtual int32_t GetIndex(FWL_HGRIDCOLROW hColRow);
  virtual FX_FLOAT GetSize(FWL_HGRIDCOLROW hColRow, FWL_GRIDUNIT& eUnit);
  virtual FWL_ERR SetSize(FWL_HGRIDCOLROW hColRow,
                          FX_FLOAT fSize,
                          FWL_GRIDUNIT eUnit);
  FX_FLOAT GetMinSize(FWL_HGRIDCOLROW hColRow, FWL_GRIDUNIT& eUnit);
  FWL_ERR SetMinSize(FWL_HGRIDCOLROW hColRow,
                     FX_FLOAT fSize,
                     FWL_GRIDUNIT eUnit);
  FX_FLOAT GetMaxSize(FWL_HGRIDCOLROW hColRow, FWL_GRIDUNIT& eUnit);
  FWL_ERR SetMaxSize(FWL_HGRIDCOLROW hColRow,
                     FX_FLOAT fSize,
                     FWL_GRIDUNIT eUnit);
  virtual FX_BOOL DeleteColRow(FWL_HGRIDCOLROW hColRow);
  virtual FX_BOOL IsColumn(FWL_HGRIDCOLROW hColRow);
  virtual int32_t GetWidgetPos(IFWL_Widget* pWidget, FX_BOOL bColumn);
  virtual FWL_ERR SetWidgetPos(IFWL_Widget* pWidget,
                               int32_t iPos,
                               FX_BOOL bColumn);
  virtual int32_t GetWidgetSpan(IFWL_Widget* pWidget, FX_BOOL bColumn);
  virtual FWL_ERR SetWidgetSpan(IFWL_Widget* pWidget,
                                int32_t iSpan,
                                FX_BOOL bColumn);
  virtual FX_FLOAT GetWidgetSize(IFWL_Widget* pWidget,
                                 FWL_GRIDSIZE eSize,
                                 FWL_GRIDUNIT& eUnit);
  virtual FWL_ERR SetWidgetSize(IFWL_Widget* pWidget,
                                FWL_GRIDSIZE eSize,
                                FX_FLOAT fSize,
                                FWL_GRIDUNIT eUit);
  virtual FX_BOOL GetWidgetMargin(IFWL_Widget* pWidget,
                                  FWL_GRIDMARGIN eMargin,
                                  FX_FLOAT& fMargin);
  virtual FWL_ERR SetWidgetMargin(IFWL_Widget* pWidget,
                                  FWL_GRIDMARGIN eMargin,
                                  FX_FLOAT fMargin);
  virtual FWL_ERR RemoveWidgetMargin(IFWL_Widget* pWidget,
                                     FWL_GRIDMARGIN eMargin);
  virtual FX_FLOAT GetGridSize(FWL_GRIDSIZE eSize, FWL_GRIDUNIT& eUnit);
  virtual FWL_ERR SetGridSize(FWL_GRIDSIZE eSize,
                              FX_FLOAT fSize,
                              FWL_GRIDUNIT eUit);

 protected:
  CFWL_GridWidgetInfo* GetWidgetInfo(IFWL_Widget* pWidget);
  void ProcFixedColRow(CFWL_GridColRow* pColRow,
                       int32_t nIndex,
                       FX_FLOAT fColRowSize,
                       FX_BOOL bColumn);
  void ProcAutoColRow(CFWL_GridColRow* pColRow,
                      int32_t nIndex,
                      FX_BOOL bColumn);
  void ProcScaledColRow(CFWL_GridColRow* pColRow,
                        int32_t nIndex,
                        FX_FLOAT fColRowSize,
                        FX_BOOL bColumn);
  void CalcWidgetWidth(IFWL_Widget* pWidget,
                       CFWL_GridWidgetInfo* pInfo,
                       FX_FLOAT fColunmWidth);
  void CalcWidgetHeigt(IFWL_Widget* pWidget,
                       CFWL_GridWidgetInfo* pInfo,
                       FX_FLOAT fRowHeigt);
  FX_FLOAT CalcAutoColumnWidgetWidth(IFWL_Widget* pWidget,
                                     CFWL_GridWidgetInfo* pInfo);
  FX_FLOAT CalcAutoColumnWidgetHeight(IFWL_Widget* pWidget,
                                      CFWL_GridWidgetInfo* pInfo);
  FX_FLOAT ProcessColumns(FX_FLOAT fWidth);
  FX_FLOAT ProcessRows(FX_FLOAT fHeight);
  FX_FLOAT ProcessUnCertainColumns();
  FX_FLOAT ProcessUnCertainRows();
  FX_BOOL SetColRowActualSize(CFWL_GridColRow* pColRow,
                              FX_FLOAT fSize,
                              FX_BOOL bSetBeyond = FALSE);
  FX_FLOAT SetWidgetActualWidth(CFWL_GridWidgetInfo* pInfo, FX_FLOAT fWidth);
  FX_FLOAT SetWidgetActualHeight(CFWL_GridWidgetInfo* pInfo, FX_FLOAT fHeight);
  void SetAllWidgetsRect();
  FX_BOOL IsGrid(IFWL_Widget* pWidget);
  void SetSpanAutoColRowSize(const CFX_PtrArray& spanAutos,
                             FX_FLOAT fTotalSize);
  void SetSpanScaledColRowSize(const CFX_PtrArray& spanScaleds,
                               FX_FLOAT fTotalSize,
                               FX_FLOAT fTotalScaledNum);
  void SetScaledColRowsSize(const CFX_PtrArray& spanScaleds,
                            FX_FLOAT fTotalSize,
                            FX_FLOAT fTotalScaledNum);
  CFX_PtrArray m_Rows;
  CFX_PtrArray m_Columns;
  CFX_PtrArray m_Widgets;
  CFX_MapPtrToPtr m_mapWidgetInfo;
  CFWL_GridLength m_Size[6];
  friend class CFWL_GridImpDelegate;
};

class CFWL_GridImpDelegate : public CFWL_WidgetImpDelegate {
 public:
  CFWL_GridImpDelegate(CFWL_GridImp* pOwner);
  int32_t OnProcessMessage(CFWL_Message* pMessage) override;
  FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics,
                       const CFX_Matrix* pMatrix = NULL) override;

 protected:
  CFWL_GridImp* m_pOwner;
};

#endif  // XFA_SRC_FWL_CORE_FWL_GRIDIMP_H_
