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