// 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 "third_party/base/ptr_util.h"
#include "xfa/fde/cfde_txtedtbuf.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();
  wchar_t wcAlias = 0;
  if (pParam->dwMode & FDE_TEXTEDITMODE_Password)
    wcAlias = m_pEngine->GetAliasChar();

  std::unique_ptr<IFX_CharIter> pIter(new CFDE_TxtEdtBuf::Iterator(
      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;
  CFX_BreakType dwBreakStatus = CFX_BreakType::None;
  do {
    if (bReload) {
      dwBreakStatus = pTxtBreak->EndBreak(CFX_BreakType::Paragraph);
    } else {
      wchar_t wAppend = pIter->GetChar();
      dwBreakStatus = pTxtBreak->AppendChar(wAppend);
    }
    if (pIter->GetAt() + 1 == nEndIndex &&
        CFX_BreakTypeNoneOrPiece(dwBreakStatus)) {
      dwBreakStatus = pTxtBreak->EndBreak(CFX_BreakType::Paragraph);
    }
    if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus)) {
      int32_t nCount = pTxtBreak->CountBreakPieces();
      int32_t nTotal = 0;
      for (int32_t j = 0; j < nCount; j++) {
        const CFX_BreakPiece* Piece = pTxtBreak->GetBreakPiece(j);
        nTotal += Piece->GetLength();
      }
      LineBaseArr.Add(nTotal);
      pTxtBreak->ClearBreakPieces();
    }
    if (pIter->GetAt() + 1 == nEndIndex &&
        dwBreakStatus == CFX_BreakType::Line) {
      bReload = true;
      pIter->Next(true);
    }
  } while (pIter->Next(false) && (pIter->GetAt() < nEndIndex));
  pTxtBreak->EndBreak(CFX_BreakType::Paragraph);
  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;
  CFX_BreakType dwBreakStatus = CFX_BreakType::None;
  int32_t nEndIndex = m_nCharStart + m_nCharCount;
  auto pIter = pdfium::MakeUnique<CFDE_TxtEdtBuf::Iterator>(
      static_cast<CFDE_TxtEdtBuf*>(pTxtBuf));
  pIter->SetAt(m_nCharStart);
  bool bReload = false;
  do {
    if (bReload) {
      dwBreakStatus = pTxtBreak->EndBreak(CFX_BreakType::Paragraph);
    } else {
      wchar_t wAppend = pIter->GetChar();
      dwBreakStatus = pTxtBreak->AppendChar(wAppend);
    }
    if (pIter->GetAt() + 1 == nEndIndex &&
        CFX_BreakTypeNoneOrPiece(dwBreakStatus)) {
      dwBreakStatus = pTxtBreak->EndBreak(CFX_BreakType::Paragraph);
    }
    if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus)) {
      nCount++;
      pTxtBreak->ClearBreakPieces();
    }
    if (pIter->GetAt() + 1 == nEndIndex &&
        dwBreakStatus == CFX_BreakType::Line) {
      bReload = true;
      pIter->Next(true);
    }
  } while (pIter->Next(false) && (pIter->GetAt() < nEndIndex));
  pTxtBreak->EndBreak(CFX_BreakType::Paragraph);
  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;
}
