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

#include "core/fxcrt/ifx_chariter.h"
#include "third_party/base/ptr_util.h"
#include "third_party/base/stl_util.h"
#include "xfa/fde/cfde_txtedtbuf.h"
#include "xfa/fde/cfde_txtedtengine.h"
#include "xfa/fde/ifde_txtedtengine.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();

  auto pIter = pdfium::MakeUnique<CFDE_TxtEdtBuf::Iterator>(
      static_cast<CFDE_TxtEdtBuf*>(pTxtBuf), wcAlias);
  pIter->SetAt(m_nCharStart);
  int32_t nEndIndex = m_nCharStart + m_nCharCount;
  std::vector<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->GetBreakPieceUnstable(j);
        nTotal += Piece->GetLength();
      }
      LineBaseArr.push_back(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 = pdfium::CollectionSize<int32_t>(LineBaseArr);
  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];
}

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;
}
