// Copyright 2014 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 "public/fpdf_save.h"

#include <stdint.h>

#include <optional>
#include <utility>
#include <vector>

#include "build/build_config.h"
#include "constants/catalog.h"
#include "core/fpdfapi/edit/cpdf_creator.h"
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/parser/cpdf_reference.h"
#include "core/fpdfapi/parser/cpdf_stream_acc.h"
#include "core/fpdfapi/parser/cpdf_string.h"
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/mask.h"
#include "core/fxcrt/stl_util.h"
#include "fpdfsdk/cpdfsdk_filewriteadapter.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
#include "public/fpdf_edit.h"

#ifdef PDF_ENABLE_XFA
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fxcrt/cfx_memorystream.h"
#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
#include "public/fpdf_formfill.h"
#endif

static_assert(FPDF_INCREMENTAL == CPDF_Creator::CreateFlags::kIncremental);
static_assert(FPDF_NO_INCREMENTAL == CPDF_Creator::CreateFlags::kNoOriginal);
static_assert(FPDF_REMOVE_SECURITY_DEPRECATED ==
              CPDF_Creator::CreateFlags::kRemoveSecurityDeprecated);
static_assert(FPDF_REMOVE_SECURITY ==
              CPDF_Creator::CreateFlags::kRemoveSecurity);
static_assert(FPDF_SUBSET_NEW_FONTS ==
              CPDF_Creator::CreateFlags::kSubsetNewFonts);

namespace {

#ifdef PDF_ENABLE_XFA
bool SaveXFADocumentData(
    CPDFXFA_Context* context,
    std::vector<RetainPtr<IFX_SeekableStream>>* file_list) {
  if (!context) {
    return false;
  }

  if (!context->ContainsExtensionForm()) {
    return true;
  }

  CPDF_Document* doc = context->GetPDFDoc();
  if (!doc) {
    return false;
  }

  RetainPtr<CPDF_Dictionary> root = doc->GetMutableRoot();
  if (!root) {
    return false;
  }

  RetainPtr<CPDF_Dictionary> acro_form =
      root->GetMutableDictFor(pdfium::catalog::kAcroForm);
  if (!acro_form) {
    return false;
  }

  RetainPtr<CPDF_Object> xfa = acro_form->GetMutableObjectFor("XFA");
  if (!xfa) {
    return true;
  }

  CPDF_Array* xfa_array = xfa->AsMutableArray();
  if (!xfa_array) {
    return false;
  }

  int size = fxcrt::CollectionSize<int>(*xfa_array);
  int form_index = -1;
  int datasets_index = -1;
  for (int i = 0; i < size - 1; i++) {
    RetainPtr<const CPDF_Object> xfa_obj = xfa_array->GetObjectAt(i);
    if (!xfa_obj->IsString()) {
      continue;
    }
    if (xfa_obj->GetString() == "form") {
      form_index = i + 1;
    } else if (xfa_obj->GetString() == "datasets") {
      datasets_index = i + 1;
    }
  }

  RetainPtr<CPDF_Stream> form_stream;
  if (form_index != -1) {
    // Get form CPDF_Stream
    RetainPtr<CPDF_Object> form_obj = xfa_array->GetMutableObjectAt(form_index);
    if (form_obj->IsReference()) {
      RetainPtr<CPDF_Object> form_direct_obj = form_obj->GetMutableDirect();
      if (form_direct_obj && form_direct_obj->IsStream()) {
        form_stream.Reset(form_direct_obj->AsMutableStream());
      }
    } else if (form_obj->IsStream()) {
      form_stream.Reset(form_obj->AsMutableStream());
    }
  }

  RetainPtr<CPDF_Stream> datasets_stream;
  if (datasets_index != -1) {
    // Get datasets CPDF_Stream
    RetainPtr<CPDF_Object> datasets_obj =
        xfa_array->GetMutableObjectAt(datasets_index);
    if (datasets_obj->IsReference()) {
      CPDF_Reference* datasets_ref_obj = datasets_obj->AsMutableReference();
      RetainPtr<CPDF_Object> datasets_direct_obj =
          datasets_ref_obj->GetMutableDirect();
      if (datasets_direct_obj && datasets_direct_obj->IsStream()) {
        datasets_stream.Reset(datasets_direct_obj->AsMutableStream());
      }
    } else if (datasets_obj->IsStream()) {
      datasets_stream.Reset(datasets_obj->AsMutableStream());
    }
  }
  // L"datasets"
  {
    RetainPtr<IFX_SeekableStream> file_write =
        pdfium::MakeRetain<CFX_MemoryStream>();
    if (context->SaveDatasetsPackage(file_write) && file_write->GetSize() > 0) {
      if (datasets_index != -1) {
        if (datasets_stream) {
          datasets_stream->InitStreamFromFile(file_write);
        }
      } else {
        auto data_stream = doc->NewIndirect<CPDF_Stream>(
            file_write, doc->New<CPDF_Dictionary>());
        int last_index = fxcrt::CollectionSize<int>(*xfa_array) - 2;
        xfa_array->InsertNewAt<CPDF_String>(last_index, "datasets");
        xfa_array->InsertNewAt<CPDF_Reference>(last_index + 1, doc,
                                               data_stream->GetObjNum());
      }
      file_list->push_back(std::move(file_write));
    }
  }
  // L"form"
  {
    RetainPtr<IFX_SeekableStream> file_write =
        pdfium::MakeRetain<CFX_MemoryStream>();
    if (context->SaveFormPackage(file_write) && file_write->GetSize() > 0) {
      if (form_index != -1) {
        if (form_stream) {
          form_stream->InitStreamFromFile(file_write);
        }
      } else {
        auto data_stream = doc->NewIndirect<CPDF_Stream>(
            file_write, doc->New<CPDF_Dictionary>());
        int last_index = fxcrt::CollectionSize<int>(*xfa_array) - 2;
        xfa_array->InsertNewAt<CPDF_String>(last_index, "form");
        xfa_array->InsertNewAt<CPDF_Reference>(last_index + 1, doc,
                                               data_stream->GetObjNum());
      }
      file_list->push_back(std::move(file_write));
    }
  }
  return true;
}
#endif  // PDF_ENABLE_XFA

bool DoDocSave(FPDF_DOCUMENT document,
               FPDF_FILEWRITE* file_write,
               FPDF_DWORD flags,
               std::optional<int> version) {
  CPDF_Document* doc = CPDFDocumentFromFPDFDocument(document);
  if (!doc) {
    return false;
  }

#ifdef PDF_ENABLE_XFA
  auto* context = static_cast<CPDFXFA_Context*>(doc->GetExtension());
  if (context) {
    std::vector<RetainPtr<IFX_SeekableStream>> file_list;
    context->SendPreSaveToXFADoc(&file_list);
    SaveXFADocumentData(context, &file_list);
  }
#endif  // PDF_ENABLE_XFA

  CPDF_Creator file_maker(
      doc, pdfium::MakeRetain<CPDFSDK_FileWriteAdapter>(file_write));
  bool create_result = file_maker.Create(
      Mask<CPDF_Creator::CreateFlags>::FromUnderlyingUnchecked(
          static_cast<uint32_t>(flags)),
      version.value_or(0));

#ifdef PDF_ENABLE_XFA
  if (context) {
    context->SendPostSaveToXFADoc();
  }
#endif  // PDF_ENABLE_XFA

  return create_result;
}

}  // namespace

FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SaveAsCopy(FPDF_DOCUMENT document,
                                                    FPDF_FILEWRITE* file_write,
                                                    FPDF_DWORD flags) {
  return DoDocSave(document, file_write, flags, {});
}

FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDF_SaveWithVersion(FPDF_DOCUMENT document,
                     FPDF_FILEWRITE* file_write,
                     FPDF_DWORD flags,
                     int fileVersion) {
  return DoDocSave(document, file_write, flags, fileVersion);
}
