// 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 CORE_INCLUDE_FPDFDOC_FPDF_VT_H_
#define CORE_INCLUDE_FPDFDOC_FPDF_VT_H_

#include "../fpdfapi/fpdf_parser.h"
#include "../fxge/fx_dib.h"

class IPDF_VariableText;
class IPDF_VariableText_Iterator;
class IPDF_VariableText_Provider;
struct CPVT_Line;
struct CPVT_Section;
struct CPVT_Word;
struct CPVT_WordPlace;
struct CPVT_WordRange;

struct CPVT_WordPlace {
  CPVT_WordPlace() : nSecIndex(-1), nLineIndex(-1), nWordIndex(-1) {}

  CPVT_WordPlace(int32_t other_nSecIndex,
                 int32_t other_nLineIndex,
                 int32_t other_nWordIndex) {
    nSecIndex = other_nSecIndex;
    nLineIndex = other_nLineIndex;
    nWordIndex = other_nWordIndex;
  }

  void Default() { nSecIndex = nLineIndex = nWordIndex = -1; }

  FX_BOOL operator==(const CPVT_WordPlace& wp) const {
    return wp.nSecIndex == nSecIndex && wp.nLineIndex == nLineIndex &&
           wp.nWordIndex == nWordIndex;
  }

  FX_BOOL operator!=(const CPVT_WordPlace& wp) const {
    return wp.nSecIndex != nSecIndex || wp.nLineIndex != nLineIndex ||
           wp.nWordIndex != nWordIndex;
  }

  inline int32_t WordCmp(const CPVT_WordPlace& wp) const {
    if (nSecIndex > wp.nSecIndex) {
      return 1;
    }
    if (nSecIndex < wp.nSecIndex) {
      return -1;
    }
    if (nLineIndex > wp.nLineIndex) {
      return 1;
    }
    if (nLineIndex < wp.nLineIndex) {
      return -1;
    }
    if (nWordIndex > wp.nWordIndex) {
      return 1;
    }
    if (nWordIndex < wp.nWordIndex) {
      return -1;
    }
    return 0;
  }

  inline int32_t LineCmp(const CPVT_WordPlace& wp) const {
    if (nSecIndex > wp.nSecIndex) {
      return 1;
    }
    if (nSecIndex < wp.nSecIndex) {
      return -1;
    }
    if (nLineIndex > wp.nLineIndex) {
      return 1;
    }
    if (nLineIndex < wp.nLineIndex) {
      return -1;
    }
    return 0;
  }

  inline int32_t SecCmp(const CPVT_WordPlace& wp) const {
    if (nSecIndex > wp.nSecIndex) {
      return 1;
    }
    if (nSecIndex < wp.nSecIndex) {
      return -1;
    }
    return 0;
  }

  int32_t nSecIndex;

  int32_t nLineIndex;

  int32_t nWordIndex;
};
struct CPVT_WordRange {
  CPVT_WordRange() {}

  CPVT_WordRange(const CPVT_WordPlace& begin, const CPVT_WordPlace& end) {
    Set(begin, end);
  }

  void Default() {
    BeginPos.Default();
    EndPos.Default();
  }

  void Set(const CPVT_WordPlace& begin, const CPVT_WordPlace& end) {
    BeginPos = begin;
    EndPos = end;
    SwapWordPlace();
  }

  void SetBeginPos(const CPVT_WordPlace& begin) {
    BeginPos = begin;
    SwapWordPlace();
  }

  void SetEndPos(const CPVT_WordPlace& end) {
    EndPos = end;
    SwapWordPlace();
  }

  FX_BOOL IsExist() const { return BeginPos != EndPos; }

  FX_BOOL operator!=(const CPVT_WordRange& wr) const {
    return wr.BeginPos != BeginPos || wr.EndPos != EndPos;
  }

  void SwapWordPlace() {
    if (BeginPos.WordCmp(EndPos) > 0) {
      CPVT_WordPlace place = EndPos;
      EndPos = BeginPos;
      BeginPos = place;
    }
  }

  CPVT_WordPlace BeginPos;

  CPVT_WordPlace EndPos;
};
struct CPVT_SecProps {
  CPVT_SecProps() : fLineLeading(0.0f), fLineIndent(0.0f), nAlignment(0) {}

  CPVT_SecProps(FX_FLOAT lineLeading, FX_FLOAT lineIndent, int32_t alignment)
      : fLineLeading(lineLeading),
        fLineIndent(lineIndent),
        nAlignment(alignment) {}

  CPVT_SecProps(const CPVT_SecProps& other)
      : fLineLeading(other.fLineLeading),
        fLineIndent(other.fLineIndent),
        nAlignment(other.nAlignment) {}

  FX_FLOAT fLineLeading;

  FX_FLOAT fLineIndent;

  int32_t nAlignment;
};
struct CPVT_WordProps {
  CPVT_WordProps()
      : nFontIndex(-1),
        fFontSize(0.0f),
        dwWordColor(0),
        nScriptType(0),
        nWordStyle(0),
        fCharSpace(0.0f),
        nHorzScale(0) {}

  CPVT_WordProps(int32_t fontIndex,
                 FX_FLOAT fontSize,
                 FX_COLORREF wordColor = 0,
                 int32_t scriptType = 0,
                 int32_t wordStyle = 0,
                 FX_FLOAT charSpace = 0,
                 int32_t horzScale = 100)
      : nFontIndex(fontIndex),
        fFontSize(fontSize),
        dwWordColor(wordColor),
        nScriptType(scriptType),
        nWordStyle(wordStyle),
        fCharSpace(charSpace),
        nHorzScale(horzScale) {}

  CPVT_WordProps(const CPVT_WordProps& other)
      : nFontIndex(other.nFontIndex),
        fFontSize(other.fFontSize),
        dwWordColor(other.dwWordColor),
        nScriptType(other.nScriptType),
        nWordStyle(other.nWordStyle),
        fCharSpace(other.fCharSpace),
        nHorzScale(other.nHorzScale) {}

  int32_t nFontIndex;

  FX_FLOAT fFontSize;

  FX_COLORREF dwWordColor;

  int32_t nScriptType;

  int32_t nWordStyle;

  FX_FLOAT fCharSpace;

  int32_t nHorzScale;
};
struct CPVT_Word {
  CPVT_Word()
      : Word(0),
        nCharset(0),
        ptWord(0, 0),
        fAscent(0.0f),
        fDescent(0.0f),
        fWidth(0.0f),
        fFontSize(0),
        WordProps() {}

  FX_WORD Word;

  int32_t nCharset;

  CPVT_WordPlace WordPlace;

  CPDF_Point ptWord;

  FX_FLOAT fAscent;

  FX_FLOAT fDescent;

  FX_FLOAT fWidth;

  int32_t nFontIndex;

  FX_FLOAT fFontSize;

  CPVT_WordProps WordProps;
};
struct CPVT_Line {
  CPVT_Line()
      : ptLine(0, 0), fLineWidth(0.0f), fLineAscent(0.0f), fLineDescent(0.0f) {}

  CPVT_WordPlace lineplace;

  CPVT_WordPlace lineEnd;

  CPDF_Point ptLine;

  FX_FLOAT fLineWidth;

  FX_FLOAT fLineAscent;

  FX_FLOAT fLineDescent;
};
struct CPVT_Section {
  CPVT_WordPlace secplace;

  CPDF_Rect rcSection;

  CPVT_SecProps SecProps;

  CPVT_WordProps WordProps;
};
class IPDF_VariableText_Provider {
 public:
  virtual ~IPDF_VariableText_Provider() {}

  virtual int32_t GetCharWidth(int32_t nFontIndex,
                               FX_WORD word,
                               int32_t nWordStyle) = 0;

  virtual int32_t GetTypeAscent(int32_t nFontIndex) = 0;

  virtual int32_t GetTypeDescent(int32_t nFontIndex) = 0;

  virtual int32_t GetWordFontIndex(FX_WORD word,
                                   int32_t charset,
                                   int32_t nFontIndex) = 0;

  virtual FX_BOOL IsLatinWord(FX_WORD word) = 0;

  virtual int32_t GetDefaultFontIndex() = 0;
};
class IPDF_VariableText_Iterator {
 public:
  virtual ~IPDF_VariableText_Iterator() {}

  virtual FX_BOOL NextWord() = 0;

  virtual FX_BOOL PrevWord() = 0;

  virtual FX_BOOL NextLine() = 0;

  virtual FX_BOOL PrevLine() = 0;

  virtual FX_BOOL NextSection() = 0;

  virtual FX_BOOL PrevSection() = 0;

  virtual FX_BOOL GetWord(CPVT_Word& word) const = 0;

  virtual FX_BOOL SetWord(const CPVT_Word& word) = 0;

  virtual FX_BOOL GetLine(CPVT_Line& line) const = 0;

  virtual FX_BOOL GetSection(CPVT_Section& section) const = 0;

  virtual FX_BOOL SetSection(const CPVT_Section& section) = 0;

  virtual void SetAt(int32_t nWordIndex) = 0;

  virtual void SetAt(const CPVT_WordPlace& place) = 0;

  virtual const CPVT_WordPlace& GetAt() const = 0;
};
class IPDF_VariableText {
 public:
  static IPDF_VariableText* NewVariableText();

  static void DelVariableText(IPDF_VariableText* pVT);

  virtual IPDF_VariableText_Provider* SetProvider(
      IPDF_VariableText_Provider* pProvider) = 0;

  virtual IPDF_VariableText_Iterator* GetIterator() = 0;

  virtual void SetPlateRect(const CPDF_Rect& rect) = 0;

  virtual void SetAlignment(int32_t nFormat = 0) = 0;

  virtual void SetPasswordChar(FX_WORD wSubWord = '*') = 0;

  virtual void SetLimitChar(int32_t nLimitChar = 0) = 0;

  virtual void SetCharArray(int32_t nCharArray = 0) = 0;

  virtual void SetCharSpace(FX_FLOAT fCharSpace = 0.0f) = 0;

  virtual void SetHorzScale(int32_t nHorzScale = 100) = 0;

  virtual void SetMultiLine(FX_BOOL bMultiLine = TRUE) = 0;

  virtual void SetAutoReturn(FX_BOOL bAuto = TRUE) = 0;

  virtual void SetAutoFontSize(FX_BOOL bAuto = TRUE) = 0;

  virtual void SetFontSize(FX_FLOAT fFontSize) = 0;

  virtual void SetLineLeading(FX_FLOAT fLineLeading) = 0;

  virtual void SetRichText(FX_BOOL bRichText) = 0;

  virtual void Initialize() = 0;

  virtual FX_BOOL IsValid() const = 0;

  virtual FX_BOOL IsRichText() const = 0;

  virtual void RearrangeAll() = 0;

  virtual void RearrangePart(const CPVT_WordRange& PlaceRange) = 0;

  virtual void ResetAll() = 0;

  virtual void SetText(const FX_WCHAR* text,
                       int32_t charset = 1,
                       const CPVT_SecProps* pSecProps = NULL,
                       const CPVT_WordProps* pWordProps = NULL) = 0;

  virtual CPVT_WordPlace InsertWord(
      const CPVT_WordPlace& place,
      FX_WORD word,
      int32_t charset = 1,
      const CPVT_WordProps* pWordProps = NULL) = 0;

  virtual CPVT_WordPlace InsertSection(
      const CPVT_WordPlace& place,
      const CPVT_SecProps* pSecProps = NULL,
      const CPVT_WordProps* pWordProps = NULL) = 0;

  virtual CPVT_WordPlace InsertText(
      const CPVT_WordPlace& place,
      const FX_WCHAR* text,
      int32_t charset = 1,
      const CPVT_SecProps* pSecProps = NULL,
      const CPVT_WordProps* pWordProps = NULL) = 0;

  virtual CPVT_WordPlace DeleteWords(const CPVT_WordRange& PlaceRange) = 0;

  virtual CPVT_WordPlace DeleteWord(const CPVT_WordPlace& place) = 0;

  virtual CPVT_WordPlace BackSpaceWord(const CPVT_WordPlace& place) = 0;

  virtual const CPDF_Rect& GetPlateRect() const = 0;

  virtual CPDF_Rect GetContentRect() const = 0;

  virtual int32_t GetTotalWords() const = 0;

  virtual FX_FLOAT GetFontSize() const = 0;

  virtual int32_t GetAlignment() const = 0;

  virtual FX_WORD GetPasswordChar() const = 0;

  virtual int32_t GetCharArray() const = 0;

  virtual int32_t GetLimitChar() const = 0;

  virtual FX_BOOL IsMultiLine() const = 0;

  virtual int32_t GetHorzScale() const = 0;

  virtual FX_FLOAT GetCharSpace() const = 0;

  virtual CPVT_WordPlace GetBeginWordPlace() const = 0;

  virtual CPVT_WordPlace GetEndWordPlace() const = 0;

  virtual CPVT_WordPlace GetPrevWordPlace(
      const CPVT_WordPlace& place) const = 0;

  virtual CPVT_WordPlace GetNextWordPlace(
      const CPVT_WordPlace& place) const = 0;

  virtual CPVT_WordPlace SearchWordPlace(const CPDF_Point& point) const = 0;

  virtual CPVT_WordPlace GetUpWordPlace(const CPVT_WordPlace& place,
                                        const CPDF_Point& point) const = 0;

  virtual CPVT_WordPlace GetDownWordPlace(const CPVT_WordPlace& place,
                                          const CPDF_Point& point) const = 0;

  virtual CPVT_WordPlace GetLineBeginPlace(
      const CPVT_WordPlace& place) const = 0;

  virtual CPVT_WordPlace GetLineEndPlace(const CPVT_WordPlace& place) const = 0;

  virtual CPVT_WordPlace GetSectionBeginPlace(
      const CPVT_WordPlace& place) const = 0;

  virtual CPVT_WordPlace GetSectionEndPlace(
      const CPVT_WordPlace& place) const = 0;

  virtual void UpdateWordPlace(CPVT_WordPlace& place) const = 0;

  virtual CPVT_WordPlace AjustLineHeader(const CPVT_WordPlace& place,
                                         FX_BOOL bPrevOrNext) const = 0;

  virtual int32_t WordPlaceToWordIndex(const CPVT_WordPlace& place) const = 0;

  virtual CPVT_WordPlace WordIndexToWordPlace(int32_t index) const = 0;

 protected:
  ~IPDF_VariableText() {}
};

#endif  // CORE_INCLUDE_FPDFDOC_FPDF_VT_H_