// Copyright 2013 The Chromium 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 "chrome/common/media_galleries/pmp_test_helper.h"

#include <algorithm>
#include <iterator>

#include "base/file_util.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/media_galleries/picasa_types.h"

namespace picasa {

namespace {

// Flatten a vector of elements into an array of bytes.
template<class T>
std::vector<char> Flatten(const std::vector<T>& elems) {
  if (elems.empty())
    return std::vector<char>();

  const uint8* elems0 = reinterpret_cast<const uint8*>(&elems[0]);
  std::vector<char> data_body(elems0, elems0 + sizeof(T) * elems.size());
  return data_body;
}

// Custom specialization for std::string.
template<>
std::vector<char> Flatten(const std::vector<std::string>& strings) {
  std::vector<char> totalchars;

  for (std::vector<std::string>::const_iterator it = strings.begin();
      it != strings.end(); ++it) {
    std::copy(it->begin(), it->end(), std::back_inserter(totalchars));
    totalchars.push_back('\0');  // Add the null termination too.
  }

  return totalchars;
}

// Returns a new vector with the concatenated contents of |a| and |b|.
std::vector<char> CombinedVectors(const std::vector<char>& a,
                                  const std::vector<char>& b) {
  std::vector<char> total;

  std::copy(a.begin(), a.end(), std::back_inserter(total));
  std::copy(b.begin(), b.end(), std::back_inserter(total));

  return total;
}

}  // namespace

PmpTestHelper::PmpTestHelper(const std::string& table_name)
    : table_name_(table_name) {
}

bool PmpTestHelper::Init(ColumnFileDestination column_file_destination) {
  if (!root_dir_.CreateUniqueTempDir() ||
      !root_dir_.IsValid() ||
      !file_util::CreateDirectory(GetDatabaseDirPath()) ||
      !file_util::CreateDirectory(GetTempDirPath())) {
    return false;
  }

  if (column_file_destination == DATABASE_DIRECTORY)
    column_file_destination_directory_ = GetDatabaseDirPath();
  else if (column_file_destination == TEMPORARY_DIRECTORY)
    column_file_destination_directory_ = GetTempDirPath();
  else
    NOTREACHED();

  base::FilePath indicator_path = column_file_destination_directory_.Append(
      base::FilePath::FromUTF8Unsafe(table_name_ + "_0"));

  return file_util::WriteFile(indicator_path, NULL, 0) == 0;
}

base::FilePath PmpTestHelper::GetDatabaseDirPath() const {
  DCHECK(root_dir_.IsValid());
  return root_dir_.path().AppendASCII(kPicasaDatabaseDirName);
}

base::FilePath PmpTestHelper::GetTempDirPath() const {
  DCHECK(root_dir_.IsValid());
  return root_dir_.path().AppendASCII(kPicasaTempDirName);
}

template<class T>
bool PmpTestHelper::WriteColumnFileFromVector(
    const std::string& column_name, const PmpFieldType field_type,
    const std::vector<T>& elements_vector) const {
  std::string file_name = table_name_ + "_" + column_name + "." + kPmpExtension;

  base::FilePath path =
      column_file_destination_directory_.AppendASCII(file_name);

  std::vector<char> data = PmpTestHelper::MakeHeaderAndBody(
      field_type, elements_vector.size(), elements_vector);

  size_t bytes_written = file_util::WriteFile(path, &data[0], data.size());
  return (bytes_written == data.size());
}

// Explicit Instantiation for all the valid types.
template bool PmpTestHelper::WriteColumnFileFromVector<std::string>(
    const std::string&, const PmpFieldType,
    const std::vector<std::string>&) const;
template bool PmpTestHelper::WriteColumnFileFromVector<uint32>(
    const std::string&, const PmpFieldType, const std::vector<uint32>&) const;
template bool PmpTestHelper::WriteColumnFileFromVector<double>(
    const std::string&, const PmpFieldType, const std::vector<double>&) const;
template bool PmpTestHelper::WriteColumnFileFromVector<uint8>(
    const std::string&, const PmpFieldType, const std::vector<uint8>&) const;
template bool PmpTestHelper::WriteColumnFileFromVector<uint64>(
    const std::string&, const PmpFieldType, const std::vector<uint64>&) const;

// Return a vector so we don't have to worry about memory management.
std::vector<char> PmpTestHelper::MakeHeader(const PmpFieldType field_type,
                                            const uint32 row_count) {
  std::vector<char> header(picasa::kPmpHeaderSize);

  // Copy in magic bytes.
  memcpy(&header[picasa::kPmpMagic1Offset], &picasa::kPmpMagic1,
         sizeof(picasa::kPmpMagic1));
  memcpy(&header[picasa::kPmpMagic2Offset], &picasa::kPmpMagic2,
         sizeof(picasa::kPmpMagic2));
  memcpy(&header[picasa::kPmpMagic3Offset], &picasa::kPmpMagic3,
         sizeof(picasa::kPmpMagic3));
  memcpy(&header[picasa::kPmpMagic4Offset], &picasa::kPmpMagic4,
         sizeof(picasa::kPmpMagic4));

  // Copy in field type.
  uint16 field_type_short = static_cast<uint16>(field_type);
  memcpy(&header[picasa::kPmpFieldType1Offset], &field_type_short,
         sizeof(uint16));
  memcpy(&header[picasa::kPmpFieldType2Offset], &field_type_short,
         sizeof(uint16));

  // Copy in row count.
  memcpy(&header[picasa::kPmpRowCountOffset], &row_count, sizeof(uint32));

  return header;
}

template<class T>
std::vector<char> PmpTestHelper::MakeHeaderAndBody(
    const PmpFieldType field_type, const uint32 row_count,
    const std::vector<T>& elems) {
  return CombinedVectors(PmpTestHelper::MakeHeader(field_type, row_count),
                         Flatten(elems));
}

// Explicit Instantiation for all the valid types.
template std::vector<char> PmpTestHelper::MakeHeaderAndBody<std::string>(
    const PmpFieldType, const uint32, const std::vector<std::string>&);
template std::vector<char> PmpTestHelper::MakeHeaderAndBody<uint32>(
    const PmpFieldType, const uint32, const std::vector<uint32>&);
template std::vector<char> PmpTestHelper::MakeHeaderAndBody<double>(
    const PmpFieldType, const uint32, const std::vector<double>&);
template std::vector<char> PmpTestHelper::MakeHeaderAndBody<uint8>(
    const PmpFieldType, const uint32, const std::vector<uint8>&);
template std::vector<char> PmpTestHelper::MakeHeaderAndBody<uint64>(
    const PmpFieldType, const uint32, const std::vector<uint64>&);

}  // namespace picasa
