// Copyright 2017 The PDFium Authors
// 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 "core/fpdfapi/parser/cpdf_flateencoder.h"

#include <variant>

#include "constants/stream_dict_common.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_name.h"
#include "core/fpdfapi/parser/cpdf_number.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fpdfapi/parser/cpdf_stream_acc.h"
#include "core/fpdfapi/parser/fpdf_parser_decode.h"
#include "core/fxcodec/flate/flatemodule.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/numerics/safe_conversions.h"

CPDF_FlateEncoder::CPDF_FlateEncoder(RetainPtr<const CPDF_Stream> pStream,
                                     bool bFlateEncode)
    : m_pAcc(pdfium::MakeRetain<CPDF_StreamAcc>(pStream)) {
  m_pAcc->LoadAllDataRaw();

  bool bHasFilter = pStream->HasFilter();
  if (bHasFilter && !bFlateEncode) {
    auto pDestAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pStream);
    pDestAcc->LoadAllDataFiltered();

    m_Data = m_pAcc->GetSpan();
    m_pClonedDict = ToDictionary(pStream->GetDict()->Clone());
    m_pClonedDict->RemoveFor("Filter");
    DCHECK(!m_pDict);
    return;
  }
  if (bHasFilter || !bFlateEncode) {
    m_Data = m_pAcc->GetSpan();
    m_pDict = pStream->GetDict();
    DCHECK(!m_pClonedDict);
    return;
  }

  m_Data = FlateModule::Encode(m_pAcc->GetSpan());
  CHECK(!GetSpan().empty());
  m_pClonedDict = ToDictionary(pStream->GetDict()->Clone());
  m_pClonedDict->SetNewFor<CPDF_Number>(
      "Length", pdfium::checked_cast<int>(GetSpan().size()));
  m_pClonedDict->SetNewFor<CPDF_Name>("Filter", "FlateDecode");
  m_pClonedDict->RemoveFor(pdfium::stream::kDecodeParms);
  DCHECK(!m_pDict);
}

CPDF_FlateEncoder::~CPDF_FlateEncoder() = default;

void CPDF_FlateEncoder::UpdateLength(size_t size) {
  if (static_cast<size_t>(GetDict()->GetIntegerFor("Length")) == size)
    return;

  if (!m_pClonedDict) {
    m_pClonedDict = ToDictionary(m_pDict->Clone());
    m_pDict.Reset();
  }
  DCHECK(m_pClonedDict);
  DCHECK(!m_pDict);
  m_pClonedDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(size));
}

bool CPDF_FlateEncoder::WriteDictTo(IFX_ArchiveStream* archive,
                                    const CPDF_Encryptor* encryptor) const {
  return GetDict()->WriteTo(archive, encryptor);
}

const CPDF_Dictionary* CPDF_FlateEncoder::GetDict() const {
  if (m_pClonedDict) {
    DCHECK(!m_pDict);
    return m_pClonedDict.Get();
  }
  return m_pDict.Get();
}

pdfium::span<const uint8_t> CPDF_FlateEncoder::GetSpan() const {
  if (is_owned())
    return std::get<DataVector<uint8_t>>(m_Data);
  return std::get<pdfium::raw_span<const uint8_t>>(m_Data);
}
