// 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 <memory>
#include <vector>

#include "core/fpdfapi/fpdf_parser/cpdf_dictionary.h"
#include "core/fpdfapi/fpdf_parser/cpdf_name.h"
#include "core/fpdfapi/fpdf_parser/cpdf_string.h"
#include "core/fpdfdoc/include/cpdf_filespec.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(cpdf_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 == data.expected);
    // DecodeFileName is the reverse procedure of EncodeFileName.
    CFX_WideString decoded_str = CPDF_FileSpec::DecodeFileName(data.expected);
    EXPECT_TRUE(decoded_str == data.input);
  }
}

TEST(cpdf_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 == 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(CFX_WeakPtr<CFX_ByteStringPool>()));
    CPDF_FileSpec file_spec(dict_obj.get());
    CFX_WideString file_name;
    for (int i = 0; i < 5; ++i) {
      dict_obj->SetFor(keywords[i], new CPDF_String(test_data[i].input));
      EXPECT_TRUE(file_spec.GetFileName(&file_name));
      EXPECT_TRUE(file_name == test_data[i].expected);
    }

    // With all the former fields and 'FS' field suggests 'URL' type.
    dict_obj->SetStringFor("FS", "URL");
    EXPECT_TRUE(file_spec.GetFileName(&file_name));
    // Url string is not decoded.
    EXPECT_TRUE(file_name == 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(cpdf_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 == test_data.input);

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