// 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_FDE_CSS_FDE_CSSDATATABLE_H_
#define XFA_FDE_CSS_FDE_CSSDATATABLE_H_

#include "core/fxcrt/include/fx_system.h"
#include "xfa/fde/css/fde_css.h"
#include "xfa/fgas/crt/fgas_memory.h"

class CFDE_CSSFunction : public CFX_Target {
 public:
  CFDE_CSSFunction(const FX_WCHAR* pszFuncName, IFDE_CSSValueList* pArgList)
      : m_pArgList(pArgList), m_pszFuncName(pszFuncName) {
    ASSERT(pArgList != NULL);
  }
  int32_t CountArgs() const { return m_pArgList->CountValues(); }
  IFDE_CSSValue* GetArgs(int32_t index) const {
    return m_pArgList->GetValue(index);
  }
  const FX_WCHAR* GetFuncName() const { return m_pszFuncName; }

 protected:
  IFDE_CSSValueList* m_pArgList;
  const FX_WCHAR* m_pszFuncName;
};
class CFDE_CSSPrimitiveValue : public IFDE_CSSPrimitiveValue,
                               public CFX_Target {
 public:
  CFDE_CSSPrimitiveValue(const CFDE_CSSPrimitiveValue& src) { *this = src; }
  CFDE_CSSPrimitiveValue(FX_ARGB color)
      : m_eType(FDE_CSSPRIMITIVETYPE_RGB), m_dwColor(color) {}
  CFDE_CSSPrimitiveValue(FDE_CSSPROPERTYVALUE eValue)
      : m_eType(FDE_CSSPRIMITIVETYPE_Enum), m_eEnum(eValue) {}
  CFDE_CSSPrimitiveValue(FDE_CSSPRIMITIVETYPE eType, FX_FLOAT fValue)
      : m_eType(eType), m_fNumber(fValue) {}
  CFDE_CSSPrimitiveValue(FDE_CSSPRIMITIVETYPE eType, const FX_WCHAR* pValue)
      : m_eType(eType), m_pString(pValue) {
    ASSERT(m_pString != NULL);
  }
  CFDE_CSSPrimitiveValue(CFDE_CSSFunction* pFunction)
      : m_eType(FDE_CSSPRIMITIVETYPE_Function), m_pFunction(pFunction) {}

  virtual FDE_CSSPRIMITIVETYPE GetPrimitiveType() const { return m_eType; }

  virtual FX_ARGB GetRGBColor() const {
    ASSERT(m_eType == FDE_CSSPRIMITIVETYPE_RGB);
    return m_dwColor;
  }
  virtual FX_FLOAT GetFloat() const {
    ASSERT(m_eType >= FDE_CSSPRIMITIVETYPE_Number &&
           m_eType <= FDE_CSSPRIMITIVETYPE_PC);
    return m_fNumber;
  }
  virtual const FX_WCHAR* GetString(int32_t& iLength) const {
    ASSERT(m_eType >= FDE_CSSPRIMITIVETYPE_String &&
           m_eType <= FDE_CSSPRIMITIVETYPE_URI);
    iLength = FXSYS_wcslen(m_pString);
    return m_pString;
  }
  virtual FDE_CSSPROPERTYVALUE GetEnum() const {
    ASSERT(m_eType == FDE_CSSPRIMITIVETYPE_Enum);
    return m_eEnum;
  }
  virtual const FX_WCHAR* GetFuncName() const {
    ASSERT(m_eType == FDE_CSSPRIMITIVETYPE_Function);
    return m_pFunction->GetFuncName();
  }
  virtual int32_t CountArgs() const {
    ASSERT(m_eType == FDE_CSSPRIMITIVETYPE_Function);
    return m_pFunction->CountArgs();
  }
  virtual IFDE_CSSValue* GetArgs(int32_t index) const {
    ASSERT(m_eType == FDE_CSSPRIMITIVETYPE_Function);
    return m_pFunction->GetArgs(index);
  }

  FDE_CSSPRIMITIVETYPE m_eType;
  union {
    FX_ARGB m_dwColor;
    FX_FLOAT m_fNumber;
    const FX_WCHAR* m_pString;
    FDE_CSSPROPERTYVALUE m_eEnum;
    CFDE_CSSFunction* m_pFunction;
  };
};
typedef CFX_ArrayTemplate<IFDE_CSSPrimitiveValue*> CFDE_CSSPrimitiveArray;
typedef CFX_ArrayTemplate<IFDE_CSSValue*> CFDE_CSSValueArray;
class CFDE_CSSValueList : public IFDE_CSSValueList, public CFX_Target {
 public:
  CFDE_CSSValueList(IFX_MemoryAllocator* pStaticStore,
                    const CFDE_CSSValueArray& list);
  virtual int32_t CountValues() const { return m_iCount; }
  virtual IFDE_CSSValue* GetValue(int32_t index) const {
    return m_ppList[index];
  }

 protected:
  IFDE_CSSValue** m_ppList;
  int32_t m_iCount;
};
class CFDE_CSSValueListParser : public CFX_Target {
 public:
  CFDE_CSSValueListParser(const FX_WCHAR* psz, int32_t iLen, FX_WCHAR separator)
      : m_Separator(separator), m_pCur(psz), m_pEnd(psz + iLen) {
    ASSERT(psz != NULL && iLen > 0);
  }
  FX_BOOL NextValue(FDE_CSSPRIMITIVETYPE& eType,
                    const FX_WCHAR*& pStart,
                    int32_t& iLength);
  FX_WCHAR m_Separator;

 protected:
  int32_t SkipTo(FX_WCHAR wch,
                 FX_BOOL bWSSeparator = FALSE,
                 FX_BOOL bBrContinue = FALSE);
  const FX_WCHAR* m_pCur;
  const FX_WCHAR* m_pEnd;
};

#define FDE_CSSVALUETYPE_MaybeNumber 0x0100
#define FDE_CSSVALUETYPE_MaybeEnum 0x0200
#define FDE_CSSVALUETYPE_MaybeURI 0x0400
#define FDE_CSSVALUETYPE_MaybeString 0x0800
#define FDE_CSSVALUETYPE_MaybeColor 0x1000
#define FDE_CSSVALUETYPE_MaybeFunction 0x2000
#define FDE_IsOnlyValue(type, enum) \
  (((type) & ~(enum)) == FDE_CSSVALUETYPE_Primitive)
struct FDE_CSSPROPERTYTABLE {
  FDE_CSSPROPERTY eName;
  const FX_WCHAR* pszName;
  uint32_t dwHash;
  uint32_t dwType;
};
typedef FDE_CSSPROPERTYTABLE const* FDE_LPCCSSPROPERTYTABLE;

FDE_LPCCSSPROPERTYTABLE FDE_GetCSSPropertyByName(const CFX_WideStringC& wsName);
FDE_LPCCSSPROPERTYTABLE FDE_GetCSSPropertyByEnum(FDE_CSSPROPERTY eName);
struct FDE_CSSPROPERTYVALUETABLE {
  FDE_CSSPROPERTYVALUE eName;
  const FX_WCHAR* pszName;
  uint32_t dwHash;
};
typedef FDE_CSSPROPERTYVALUETABLE const* FDE_LPCCSSPROPERTYVALUETABLE;

FDE_LPCCSSPROPERTYVALUETABLE FDE_GetCSSPropertyValueByName(
    const CFX_WideStringC& wsName);
FDE_LPCCSSPROPERTYVALUETABLE FDE_GetCSSPropertyValueByEnum(
    FDE_CSSPROPERTYVALUE eName);
struct FDE_CSSMEDIATYPETABLE {
  uint16_t wHash;
  uint16_t wValue;
};
typedef FDE_CSSMEDIATYPETABLE const* FDE_LPCCSSMEDIATYPETABLE;
FDE_LPCCSSMEDIATYPETABLE FDE_GetCSSMediaTypeByName(
    const CFX_WideStringC& wsName);
struct FDE_CSSLENGTHUNITTABLE {
  uint16_t wHash;
  uint16_t wValue;
};
typedef FDE_CSSLENGTHUNITTABLE const* FDE_LPCCSSLENGTHUNITTABLE;
FDE_LPCCSSLENGTHUNITTABLE FDE_GetCSSLengthUnitByName(
    const CFX_WideStringC& wsName);
struct FDE_CSSCOLORTABLE {
  uint32_t dwHash;
  FX_ARGB dwValue;
};
typedef FDE_CSSCOLORTABLE const* FDE_LPCCSSCOLORTABLE;
FDE_LPCCSSCOLORTABLE FDE_GetCSSColorByName(const CFX_WideStringC& wsName);

struct FDE_CSSPERSUDOTABLE {
  FDE_CSSPERSUDO eName;
  const FX_WCHAR* pszName;
  uint32_t dwHash;
};
typedef FDE_CSSPERSUDOTABLE const* FDE_LPCCSSPERSUDOTABLE;

FDE_LPCCSSPERSUDOTABLE FDE_GetCSSPersudoByEnum(FDE_CSSPERSUDO ePersudo);
FX_BOOL FDE_ParseCSSNumber(const FX_WCHAR* pszValue,
                           int32_t iValueLen,
                           FX_FLOAT& fValue,
                           FDE_CSSPRIMITIVETYPE& eUnit);
FX_BOOL FDE_ParseCSSString(const FX_WCHAR* pszValue,
                           int32_t iValueLen,
                           int32_t& iOffset,
                           int32_t& iLength);
FX_BOOL FDE_ParseCSSColor(const FX_WCHAR* pszValue,
                          int32_t iValueLen,
                          FX_ARGB& dwColor);
FX_BOOL FDE_ParseCSSURI(const FX_WCHAR* pszValue,
                        int32_t iValueLen,
                        int32_t& iOffset,
                        int32_t& iLength);

#endif  // XFA_FDE_CSS_FDE_CSSDATATABLE_H_
