// Copyright 2016 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.

#include "core/include/fpdfdoc/fpdf_doc.h"

#include <memory>
#include <vector>

#include "core/fpdfapi/fpdf_parser/include/cpdf_name.h"
#include "core/fpdfapi/fpdf_parser/include/cpdf_string.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/test_support.h"

namespace {

using ScopedObj = std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>>;
using ScopedDict =
    std::unique_ptr<CPDF_Dictionary, ReleaseDeleter<CPDF_Dictionary>>;
}

TEST(doc_basic_filespec, EncodeDecodeFileName) {
  std::vector<pdfium::NullTermWstrFuncTestData> test_data = {
    // Empty src string.
    {L"", L""},
    // only file name.
    {L"test.pdf", L"test.pdf"},
#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    // With drive identifier.
    {L"r:\\pdfdocs\\spec.pdf", L"/r/pdfdocs/spec.pdf"},
    // Relative path.
    {L"My Document\\test.pdf", L"My Document/test.pdf"},
    // Absolute path without drive identifier.
    {L"\\pdfdocs\\spec.pdf", L"//pdfdocs/spec.pdf"},
    // Absolute path with double backslashes.
    {L"\\\\pdfdocs\\spec.pdf", L"/pdfdocs/spec.pdf"},
// Network resource name. It is not supported yet.
// {L"pclib/eng:\\pdfdocs\\spec.pdf", L"/pclib/eng/pdfdocs/spec.pdf"},
#elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
    // Absolute path with colon separator.
    {L"Mac HD:PDFDocs:spec.pdf", L"/Mac HD/PDFDocs/spec.pdf"},
    // Relative path with colon separator.
    {L"PDFDocs:spec.pdf", L"PDFDocs/spec.pdf"},
#else
    // Relative path.
    {L"./docs/test.pdf", L"./docs/test.pdf"},
    // Relative path with parent dir.
    {L"../test_docs/test.pdf", L"../test_docs/test.pdf"},
    // Absolute path.
    {L"/usr/local/home/test.pdf", L"/usr/local/home/test.pdf"},
#endif
  };
  for (const auto& data : test_data) {
    CFX_WideString encoded_str = CPDF_FileSpec::EncodeFileName(data.input);
    EXPECT_TRUE(encoded_str.Equal(data.expected));
    // DecodeFileName is the reverse procedure of EncodeFileName.
    CFX_WideString decoded_str = CPDF_FileSpec::DecodeFileName(data.expected);
    EXPECT_TRUE(decoded_str.Equal(data.input));
  }
}

TEST(doc_basic_filespec, GetFileName) {
  {
    // String object.
    pdfium::NullTermWstrFuncTestData test_data = {
#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
      L"/C/docs/test.pdf",
      L"C:\\docs\\test.pdf"
#elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
      L"/Mac HD/docs/test.pdf",
      L"Mac HD:docs:test.pdf"
#else
      L"/docs/test.pdf",
      L"/docs/test.pdf"
#endif
    };
    ScopedObj str_obj(new CPDF_String(test_data.input));
    CPDF_FileSpec file_spec(str_obj.get());
    CFX_WideString file_name;
    EXPECT_TRUE(file_spec.GetFileName(&file_name));
    EXPECT_TRUE(file_name.Equal(test_data.expected));
  }
  {
    // Dictionary object.
    pdfium::NullTermWstrFuncTestData test_data[5] = {
#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
      {L"/C/docs/test.pdf", L"C:\\docs\\test.pdf"},
      {L"/D/docs/test.pdf", L"D:\\docs\\test.pdf"},
      {L"/E/docs/test.pdf", L"E:\\docs\\test.pdf"},
      {L"/F/docs/test.pdf", L"F:\\docs\\test.pdf"},
      {L"/G/docs/test.pdf", L"G:\\docs\\test.pdf"},
#elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
      {L"/Mac HD/docs1/test.pdf", L"Mac HD:docs1:test.pdf"},
      {L"/Mac HD/docs2/test.pdf", L"Mac HD:docs2:test.pdf"},
      {L"/Mac HD/docs3/test.pdf", L"Mac HD:docs3:test.pdf"},
      {L"/Mac HD/docs4/test.pdf", L"Mac HD:docs4:test.pdf"},
      {L"/Mac HD/docs5/test.pdf", L"Mac HD:docs5:test.pdf"},
#else
      {L"/docs/a/test.pdf", L"/docs/a/test.pdf"},
      {L"/docs/b/test.pdf", L"/docs/b/test.pdf"},
      {L"/docs/c/test.pdf", L"/docs/c/test.pdf"},
      {L"/docs/d/test.pdf", L"/docs/d/test.pdf"},
      {L"/docs/e/test.pdf", L"/docs/e/test.pdf"},
#endif
    };
    // Keyword fields in reverse order of precedence to retrieve the file name.
    const char* const keywords[5] = {"Unix", "Mac", "DOS", "F", "UF"};
    ScopedDict dict_obj(new CPDF_Dictionary);
    CPDF_FileSpec file_spec(dict_obj.get());
    CFX_WideString file_name;
    for (int i = 0; i < 5; ++i) {
      dict_obj->SetAt(keywords[i], new CPDF_String(test_data[i].input));
      EXPECT_TRUE(file_spec.GetFileName(&file_name));
      EXPECT_TRUE(file_name.Equal(test_data[i].expected));
    }

    // With all the former fields and 'FS' field suggests 'URL' type.
    dict_obj->SetAtString("FS", "URL");
    EXPECT_TRUE(file_spec.GetFileName(&file_name));
    // Url string is not decoded.
    EXPECT_TRUE(file_name.Equal(test_data[4].input));
  }
  {
    // Invalid object.
    ScopedObj name_obj(new CPDF_Name("test.pdf"));
    CPDF_FileSpec file_spec(name_obj.get());
    CFX_WideString file_name;
    EXPECT_FALSE(file_spec.GetFileName(&file_name));
  }
}

TEST(doc_basic_filespec, SetFileName) {
  pdfium::NullTermWstrFuncTestData test_data = {
#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    L"C:\\docs\\test.pdf",
    L"/C/docs/test.pdf"
#elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
    L"Mac HD:docs:test.pdf",
    L"/Mac HD/docs/test.pdf"
#else
    L"/docs/test.pdf",
    L"/docs/test.pdf"
#endif
  };
  // String object.
  ScopedObj str_obj(new CPDF_String(L"babababa"));
  CPDF_FileSpec file_spec1(str_obj.get());
  file_spec1.SetFileName(test_data.input);
  // Check internal object value.
  CFX_ByteString str = CFX_ByteString::FromUnicode(test_data.expected);
  EXPECT_TRUE(str == str_obj->GetString());
  // Check we can get the file name back.
  CFX_WideString file_name;
  EXPECT_TRUE(file_spec1.GetFileName(&file_name));
  EXPECT_TRUE(file_name.Equal(test_data.input));

  // Dictionary object.
  ScopedDict dict_obj(new CPDF_Dictionary);
  CPDF_FileSpec file_spec2(dict_obj.get());
  file_spec2.SetFileName(test_data.input);
  // Check internal object value.
  file_name = dict_obj->GetUnicodeTextBy("F");
  EXPECT_TRUE(file_name.Equal(test_data.expected));
  file_name = dict_obj->GetUnicodeTextBy("UF");
  EXPECT_TRUE(file_name.Equal(test_data.expected));
  // Check we can get the file name back.
  EXPECT_TRUE(file_spec2.GetFileName(&file_name));
  EXPECT_TRUE(file_name.Equal(test_data.input));
}
