// 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

#include "xfa/fde/cfde_txtedtparag.h"

#include <memory>

#include "xfa/fde/cfde_txtedtbuf.h"
#include "xfa/fde/cfde_txtedtbufiter.h"
#include "xfa/fde/cfde_txtedtengine.h"
#include "xfa/fde/ifde_txtedtengine.h"
#include "xfa/fde/ifx_chariter.h"
#include "xfa/fgas/layout/fgas_textbreak.h"

CFDE_TxtEdtParag::CFDE_TxtEdtParag(CFDE_TxtEdtEngine* pEngine)
    : m_nCharStart(0),
      m_nCharCount(0),
      m_nLineCount(0),
      m_lpData(nullptr),
      m_pEngine(pEngine) {
  ASSERT(m_pEngine);
}

CFDE_TxtEdtParag::~CFDE_TxtEdtParag() {
  if (m_lpData)
    FX_Free(m_lpData);
}

void CFDE_TxtEdtParag::LoadParag() {
  if (m_lpData) {
    m_lpData[0]++;
    return;
  }
  CFX_TxtBreak* pTxtBreak = m_pEngine->GetTextBreak();
  CFDE_TxtEdtBuf* pTxtBuf = m_pEngine->GetTextBuf();
  const FDE_TXTEDTPARAMS* pParam = m_pEngine->GetEditParams();
  FX_WCHAR wcAlias = 0;
  if (pParam->dwMode & FDE_TEXTEDITMODE_Password) {
    wcAlias = m_pEngine->GetAliasChar();
  }
  std::unique_ptr<IFX_CharIter> pIter(
      new CFDE_TxtEdtBufIter(static_cast<CFDE_TxtEdtBuf*>(pTxtBuf), wcAlias));
  pIter->SetAt(m_nCharStart);
  int32_t nEndIndex = m_nCharStart + m_nCharCount;
  CFX_ArrayTemplate<int32_t> LineBaseArr;
  bool bReload = false;
  uint32_t dwBreakStatus = FX_TXTBREAK_None;
  do {
    if (bReload) {
      dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
    } else {
      FX_WCHAR wAppend = pIter->GetChar();
      dwBreakStatus = pTxtBreak->AppendChar(wAppend);
    }
    if (pIter->GetAt() + 1 == nEndIndex &&
        dwBreakStatus < FX_TXTBREAK_LineBreak) {
      dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
    }
    if (dwBreakStatus > FX_TXTBREAK_PieceBreak) {
      int32_t nCount = pTxtBreak->CountBreakPieces();
      int32_t nTotal = 0;
      for (int32_t j = 0; j < nCount; j++) {
        const CFX_TxtPiece* Piece = pTxtBreak->GetBreakPiece(j);
        nTotal += Piece->GetLength();
      }
      LineBaseArr.Add(nTotal);
      pTxtBreak->ClearBreakPieces();
    }
    if ((pIter->GetAt() + 1 == nEndIndex) &&
        (dwBreakStatus == FX_TXTBREAK_LineBreak)) {
      bReload = true;
      pIter->Next(true);
    }
  } while (pIter->Next(false) && (pIter->GetAt() < nEndIndex));
  pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
  pTxtBreak->ClearBreakPieces();
  int32_t nLineCount = LineBaseArr.GetSize();
  m_nLineCount = nLineCount;
  if (m_lpData) {
    m_lpData = FX_Realloc(int32_t, m_lpData, nLineCount + 1);
  } else {
    m_lpData = FX_Alloc(int32_t, nLineCount + 1);
  }
  int32_t* pIntArr = m_lpData;
  pIntArr[0] = 1;
  m_nLineCount = nLineCount;
  pIntArr++;
  for (int32_t j = 0; j < nLineCount; j++, pIntArr++) {
    *pIntArr = LineBaseArr[j];
  }
  LineBaseArr.RemoveAll();
}

void CFDE_TxtEdtParag::UnloadParag() {
  m_lpData[0]--;
  ASSERT(m_lpData[0] >= 0);
  if (m_lpData[0] == 0) {
    FX_Free(m_lpData);
    m_lpData = nullptr;
  }
}

void CFDE_TxtEdtParag::CalcLines() {
  CFX_TxtBreak* pTxtBreak = m_pEngine->GetTextBreak();
  CFDE_TxtEdtBuf* pTxtBuf = m_pEngine->GetTextBuf();
  int32_t nCount = 0;
  uint32_t dwBreakStatus = FX_TXTBREAK_None;
  int32_t nEndIndex = m_nCharStart + m_nCharCount;
  std::unique_ptr<IFX_CharIter> pIter(
      new CFDE_TxtEdtBufIter(static_cast<CFDE_TxtEdtBuf*>(pTxtBuf)));
  pIter->SetAt(m_nCharStart);
  bool bReload = false;
  do {
    if (bReload) {
      dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
    } else {
      FX_WCHAR wAppend = pIter->GetChar();
      dwBreakStatus = pTxtBreak->AppendChar(wAppend);
    }
    if (pIter->GetAt() + 1 == nEndIndex &&
        dwBreakStatus < FX_TXTBREAK_LineBreak) {
      dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
    }
    if (dwBreakStatus > FX_TXTBREAK_PieceBreak) {
      nCount++;
      pTxtBreak->ClearBreakPieces();
    }
    if ((pIter->GetAt() + 1 == nEndIndex) &&
        (dwBreakStatus == FX_TXTBREAK_LineBreak)) {
      bReload = true;
      pIter->Next(true);
    }
  } while (pIter->Next(false) && (pIter->GetAt() < nEndIndex));
  pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
  pTxtBreak->ClearBreakPieces();
  m_nLineCount = nCount;
}

void CFDE_TxtEdtParag::GetLineRange(int32_t nLineIndex,
                                    int32_t& nStart,
                                    int32_t& nCount) const {
  int32_t* pLineBaseArr = m_lpData;
  ASSERT(nLineIndex < m_nLineCount);
  nStart = m_nCharStart;
  pLineBaseArr++;
  for (int32_t i = 0; i < nLineIndex; i++) {
    nStart += *pLineBaseArr;
    pLineBaseArr++;
  }
  nCount = *pLineBaseArr;
}
