// Copyright (c) 2016 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 "net/tools/huffman_trie/trie/trie_writer.h"

#include <algorithm>

#include "base/logging.h"
#include "net/tools/huffman_trie/trie/trie_bit_buffer.h"

namespace net {

namespace huffman_trie {

namespace {

bool CompareReversedEntries(
    const std::unique_ptr<net::huffman_trie::ReversedEntry>& lhs,
    const std::unique_ptr<net::huffman_trie::ReversedEntry>& rhs) {
  return lhs->reversed_name < rhs->reversed_name;
}

// Searches for the longest common prefix for all entries between |start| and
// |end|.
std::vector<uint8_t> LongestCommonPrefix(ReversedEntries::const_iterator start,
                                         ReversedEntries::const_iterator end) {
  if (start == end) {
    return std::vector<uint8_t>();
  }

  std::vector<uint8_t> prefix;
  for (size_t i = 0;; ++i) {
    if (i > (*start)->reversed_name.size()) {
      break;
    }

    uint8_t candidate = (*start)->reversed_name.at(i);
    if (candidate == kTerminalValue) {
      break;
    }

    bool ok = true;
    for (auto it = start + 1; it != end; ++it) {
      if (i > (*it)->reversed_name.size() ||
          (*it)->reversed_name.at(i) != candidate) {
        ok = false;
        break;
      }
    }

    if (!ok) {
      break;
    }

    prefix.push_back(candidate);
  }

  return prefix;
}

// Returns the reversed |hostname| as a vector of bytes. The reversed hostname
// will be terminated by |kTerminalValue|.
std::vector<uint8_t> ReverseName(const std::string& hostname) {
  size_t hostname_size = hostname.size();
  std::vector<uint8_t> reversed_name(hostname_size + 1);

  for (size_t i = 0; i < hostname_size; ++i) {
    reversed_name[i] = hostname[hostname_size - i - 1];
  }

  reversed_name[reversed_name.size() - 1] = kTerminalValue;
  return reversed_name;
}

// Removes the first |length| characters from all entries between |start| and
// |end|.
void RemovePrefix(size_t length,
                  ReversedEntries::iterator start,
                  ReversedEntries::iterator end) {
  for (auto it = start; it != end; ++it) {
    (*it)->reversed_name.erase((*it)->reversed_name.begin(),
                               (*it)->reversed_name.begin() + length);
  }
}

}  // namespace

ReversedEntry::ReversedEntry(std::vector<uint8_t> reversed_name,
                             const TrieEntry* entry)
    : reversed_name(reversed_name), entry(entry) {}

ReversedEntry::~ReversedEntry() = default;

TrieWriter::TrieWriter(
    const huffman_trie::HuffmanRepresentationTable& huffman_table,
    huffman_trie::HuffmanBuilder* huffman_builder)
    : huffman_table_(huffman_table), huffman_builder_(huffman_builder) {}

TrieWriter::~TrieWriter() = default;

bool TrieWriter::WriteEntries(const TrieEntries& entries,
                              uint32_t* root_position) {
  if (entries.empty())
    return false;

  ReversedEntries reversed_entries;
  for (auto* const entry : entries) {
    std::unique_ptr<ReversedEntry> reversed_entry(
        new ReversedEntry(ReverseName(entry->name()), entry));
    reversed_entries.push_back(std::move(reversed_entry));
  }

  std::stable_sort(reversed_entries.begin(), reversed_entries.end(),
                   CompareReversedEntries);

  return WriteDispatchTables(reversed_entries.begin(), reversed_entries.end(),
                             root_position);
}

bool TrieWriter::WriteDispatchTables(ReversedEntries::iterator start,
                                     ReversedEntries::iterator end,
                                     uint32_t* position) {
  DCHECK(start != end) << "No entries passed to WriteDispatchTables";

  TrieBitBuffer writer;

  std::vector<uint8_t> prefix = LongestCommonPrefix(start, end);
  for (size_t i = 0; i < prefix.size(); ++i) {
    writer.WriteBit(1);
  }
  writer.WriteBit(0);

  if (prefix.size()) {
    for (size_t i = 0; i < prefix.size(); ++i) {
      writer.WriteChar(prefix.at(i), huffman_table_, huffman_builder_);
    }
  }

  RemovePrefix(prefix.size(), start, end);
  int32_t last_position = -1;

  while (start != end) {
    uint8_t candidate = (*start)->reversed_name.at(0);
    auto sub_entries_end = start + 1;

    for (; sub_entries_end != end; sub_entries_end++) {
      if ((*sub_entries_end)->reversed_name.at(0) != candidate) {
        break;
      }
    }

    writer.WriteChar(candidate, huffman_table_, huffman_builder_);

    if (candidate == kTerminalValue) {
      if (sub_entries_end - start != 1) {
        return false;
      }
      if (!(*start)->entry->WriteEntry(&writer)) {
        return false;
      }
    } else {
      RemovePrefix(1, start, sub_entries_end);
      uint32_t table_position;
      if (!WriteDispatchTables(start, sub_entries_end, &table_position)) {
        return false;
      }

      writer.WritePosition(table_position, &last_position);
    }

    start = sub_entries_end;
  }

  writer.WriteChar(kEndOfTableValue, huffman_table_, huffman_builder_);

  *position = buffer_.position();
  writer.Flush();
  writer.WriteToBitWriter(&buffer_);
  return true;
}

uint32_t TrieWriter::position() const {
  return buffer_.position();
}

void TrieWriter::Flush() {
  buffer_.Flush();
}

}  // namespace huffman_trie

}  // namespace net
