// Copyright 2010-2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// CandidateList and Candidate classes to be used with Session class.

#include "session/internal/candidate_list.h"

#include <algorithm>
#include <map>
#include <string>
#include <vector>

#include "base/freelist.h"
#include "base/logging.h"
#include "base/port.h"
#include "base/util.h"

namespace mozc {
namespace session {

Candidate::Candidate()
    : id_(0),
      attributes_(NO_ATTRIBUTES),
      subcandidate_list_(NULL),
      subcandidate_list_owner_(false) {}

Candidate::~Candidate() {}

void Candidate::Clear() {
  id_ = 0;
  attributes_ = NO_ATTRIBUTES;
  if (subcandidate_list_owner_ && subcandidate_list_ != NULL) {
    delete subcandidate_list_;
  }
  subcandidate_list_ = NULL;
  subcandidate_list_owner_ = false;
}

int Candidate::id() const {
  return id_;
}

void Candidate::set_id(const int id) {
  id_ = id;
}

Attributes Candidate::attributes() const {
  return attributes_;
}

void Candidate::add_attributes(const Attributes attributes) {
  attributes_ |= attributes;
}

void Candidate::set_attributes(const Attributes attributes) {
  attributes_ = attributes;
}

bool Candidate::has_attributes(const Attributes attributes) const {
  return (attributes_ & attributes) == attributes;
}

bool Candidate::IsSubcandidateList() const {
  return (subcandidate_list_ != NULL);
}

const CandidateList &Candidate::subcandidate_list() const {
  return *subcandidate_list_;
}

CandidateList *Candidate::mutable_subcandidate_list() {
  return subcandidate_list_;
}

CandidateList *Candidate::allocate_subcandidate_list(const bool rotate) {
  subcandidate_list_ = new CandidateList(rotate);
  subcandidate_list_owner_ = true;
  return subcandidate_list_;
}

void Candidate::set_subcandidate_list(CandidateList *subcandidate_list) {
  subcandidate_list_ = subcandidate_list;
}


static const size_t kDefaultPageSize = 9;

CandidateList::CandidateList(const bool rotate)
    : rotate_(rotate),
      page_size_(kDefaultPageSize),
      focused_index_(0),
      focused_(false),
      candidate_pool_(new ObjectPool<Candidate>(kDefaultPageSize)),
      candidates_(new vector<Candidate *>),
      next_available_id_(0),
      added_candidates_(new map<uint64, int>),
      alternative_ids_(new map<int, int>) {
}

CandidateList::~CandidateList() {
  Clear();
}

void CandidateList::Clear() {
  vector<Candidate *>::iterator it;
  for (it = candidates_->begin(); it != candidates_->end(); ++it) {
    (*it)->Clear();
    candidate_pool_->Release(*it);
  }
  focused_index_ = 0;
  focused_ = false;
  candidates_->clear();
  next_available_id_ = 0;
  added_candidates_->clear();
  alternative_ids_->clear();
}

const Candidate &CandidateList::GetDeepestFocusedCandidate() const {
  if (focused_candidate().IsSubcandidateList()) {
    return focused_candidate().subcandidate_list().GetDeepestFocusedCandidate();
  }
  return focused_candidate();
}

void CandidateList::AddCandidate(const int id, const string &value) {
  AddCandidateWithAttributes(id, value, NO_ATTRIBUTES);
}

void CandidateList::AddCandidateWithAttributes(const int id,
                                               const string &value,
                                               const Attributes attributes) {
  if (id >= 0) {
    DCHECK(id >= next_available_id_);
    // If id is not for T13N candidate, update |last_added_id_|.
    next_available_id_ = id + 1;
  }

  // If the value has already been stored in the candidate list, reuse it and
  // update the alternative_ids_.
  const uint64 fp = Util::Fingerprint(value);

  const pair<map<uint64, int>::iterator, bool> result =
    added_candidates_->insert(make_pair(fp, id));
  if (!result.second) {  // insertion was failed.
    const int alt_id = result.first->second;
    (*alternative_ids_)[id] = alt_id;

    // Add attributes to the existing candidate.
    for (size_t i = 0; i < size(); ++i) {
      if (candidate(i).id() == alt_id) {
        (*candidates_)[i]->add_attributes(attributes);
      }
    }
    return;
  }

  Candidate *new_candidate = candidate_pool_->Alloc();
  candidates_->push_back(new_candidate);

  new_candidate->set_id(id);
  new_candidate->set_attributes(attributes);
}

void CandidateList::AddSubCandidateList(CandidateList *subcandidate_list) {
  Candidate *new_candidate = candidate_pool_->Alloc();
  candidates_->push_back(new_candidate);

  new_candidate->set_subcandidate_list(subcandidate_list);
}

CandidateList *CandidateList::AllocateSubCandidateList(const bool rotate) {
  Candidate *new_candidate = candidate_pool_->Alloc();
  candidates_->push_back(new_candidate);

  return new_candidate->allocate_subcandidate_list(rotate);
}

void CandidateList::set_name(const string &name) {
  name_ = name;
}

const string &CandidateList::name() const {
  return name_;
}

void CandidateList::set_page_size(const size_t page_size) {
  page_size_ = page_size;
}

size_t CandidateList::page_size() const {
  return page_size_;
}

size_t CandidateList::size() const {
  return candidates_->size();
}

size_t CandidateList::last_index() const {
  return size() - 1;
}

const Candidate &CandidateList::focused_candidate() const {
  return candidate(focused_index_);
}

const Candidate &CandidateList::candidate(const size_t index) const {
  return *(*candidates_)[index];
}

bool CandidateList::focused() const {
  return focused_;
}

void CandidateList::set_focused(const bool focused) {
  focused_ = focused;
}

int CandidateList::focused_id() const {
  // If the list does not have any candidate, 0 will be returned.
  if (size() == 0) {
    return 0;
  }
  if (focused_candidate().IsSubcandidateList()) {
    return focused_candidate().subcandidate_list().focused_id();
  }
  return focused_candidate().id();
}

size_t CandidateList::focused_index() const {
  return focused_index_;
}

int CandidateList::next_available_id() const {
  int result = next_available_id_;
  for (size_t i = 0; i < candidates_->size(); ++i) {
    if (candidate(i).IsSubcandidateList()) {
      const int sub_available_id =
          candidate(i).subcandidate_list().next_available_id();
      if (result < sub_available_id) {
        result = sub_available_id;
      }
    }
  }
  return result;
}

void CandidateList::GetPageRange(const size_t index,
                                 size_t *page_begin,
                                 size_t *page_end) const {
  *page_begin = index - (index % page_size_);
  *page_end = min(last_index(), *page_begin + page_size_ - 1);
}

void CandidateList::MoveFirst() {
  focused_index_ = 0;
}

void CandidateList::MoveLast() {
  focused_index_ = last_index();
}

bool CandidateList::MoveNext() {
  // If the current candidate points to subcandidate list, the focused
  // candidate in the subcandidate list will be operated.
  if (focused_candidate().IsSubcandidateList() &&
      mutable_focused_subcandidate_list()->MoveNext()) {
    return true;
  }

  if (IsLast(focused_index_)) {
    MoveFirst();
    if (!rotate_) {
      // If this candidate list does not rotate, the focused candidate
      // is moved to the parent candidate list.
      return false;
    }
  } else {
    ++focused_index_;
  }

  // If the new current candidate points to subcandidate list, the
  // focused candidate in the subcandidate list should be the first
  // candidate.
  if (focused_candidate().IsSubcandidateList()) {
    mutable_focused_subcandidate_list()->MoveFirst();
  }
  return true;
}

bool CandidateList::MovePrev() {
  // If the current candidate points to subcandidate list, the focused
  // candidate in the subcandidate list will be operated.
  if (focused_candidate().IsSubcandidateList() &&
      mutable_focused_subcandidate_list()->MovePrev()) {
    return true;
  }

  if (IsFirst(focused_index_)) {
    MoveLast();
    if (!rotate_) {
      // If this candidate list does not rotate, the focused candidate
      // is moved to the parent candidate list.
      return false;
    }
  } else {
    --focused_index_;
  }

  // If the new current candidate points to subcandidate list, the
  // focused candidate in the subcandidate list should be the first
  // candidate.
  if (focused_candidate().IsSubcandidateList()) {
    mutable_focused_subcandidate_list()->MoveLast();
  }
  return true;
}

bool CandidateList::MoveNextPage() {
  if (focused_candidate().IsSubcandidateList() &&
      mutable_focused_subcandidate_list()->MoveNextPage()) {
    return true;
  }

  if (IsLastPage(focused_index_)) {
    if (!rotate_) {
      // If the current candidate is the last candidate and rotation
      // should not be performed, this function does nothing and
      // returns false.
      return false;
    }
    MoveFirst();
  } else {
    focused_index_ += page_size_;
  }
  // Move the forcused index to the beginning of the page.
  focused_index_ -= (focused_index_ % page_size_);

  // If the new current candidate points to subcandidate list, the
  // focused candidate in the subcandidate list should be the first
  // candidate.
  if (focused_candidate().IsSubcandidateList()) {
    mutable_focused_subcandidate_list()->MoveFirst();
  }
  return true;
}

bool CandidateList::MovePrevPage() {
  if (focused_candidate().IsSubcandidateList() &&
      mutable_focused_subcandidate_list()->MovePrevPage()) {
    return true;
  }

  if (IsFirstPage(focused_index_)) {
    if (!rotate_) {
      // If the current candidate is on the first page and rotation
      // should not be performed, this function does nothing and
      // returns false.
      return false;
    }
    MoveLast();
  } else {
    // The focused index in not on the first page, so the value of
    // (focused_index_ - page_size_) must be a positive value.
    focused_index_ -= page_size_;
  }
  // Move the forcused index to the beginning of the page.
  focused_index_ -= (focused_index_ % page_size_);

  // If the new current candidate points to subcandidate list, the
  // focused candidate in the subcandidate list should be the first
  // candidate.  Note the forcused index will be moved to the
  // beginning of the page on page moves.
  if (focused_candidate().IsSubcandidateList()) {
    mutable_focused_subcandidate_list()->MoveFirst();
  }
  return true;
}

bool CandidateList::MoveNextAttributes(const Attributes attributes) {
  // Move one candidate.
  MoveNext();
  return MoveToAttributes(attributes);
}

bool CandidateList::MoveToAttributes(const Attributes attributes) {
  const size_t cand_size = size();
  for (size_t i = 0; i < cand_size; ++i) {
    // Shift the index to make the first index focused_index_.
    const size_t index = (focused_index_ + i) % cand_size;

    Candidate *cand =  (*candidates_)[index];

    // If the candidate is a subcandidate list, the subcandidate list is
    // traversed recursively.
    if (cand->IsSubcandidateList() &&
        cand->mutable_subcandidate_list()->MoveToAttributes(attributes)) {
      focused_index_ = index;
      return true;
    } else if (cand->has_attributes(attributes)) {
      focused_index_ = index;
      return true;
    }
  }

  return false;
}

bool CandidateList::MoveToId(const int base_id) {
  int id = base_id;

  // If an alternative id for the base_id found, use it to avoid
  // duplicated candidates.
  if (alternative_ids_->find(id) != alternative_ids_->end()) {
    id = (*alternative_ids_)[id];
  }

  // NOTE(komatsu): Although this function's order is O(N), The size
  // of N is less than kMaxCandidateSize (= 200).  So it would not be
  // a problem.
  for (size_t i = 0; i < size(); ++i) {
    Candidate *cand =  (*candidates_)[i];
    // If the candidate is a subcandidate list, the subcandidate list is
    // traversed recursively.
    if (cand->IsSubcandidateList() &&
        cand->mutable_subcandidate_list()->MoveToId(id)) {
      focused_index_ = i;
      return true;
    } else if (cand->id() == id) {
      focused_index_ = i;
      return true;
    }
  }
  return false;
}

bool CandidateList::MoveToPageIndex(const size_t page_index) {
  size_t begin = 0;
  size_t end = 0;
  GetPageRange(focused_index_, &begin, &end);
  if (begin + page_index > end) {
    return false;
  }
  focused_index_ = begin + page_index;
  if (focused_candidate().IsSubcandidateList()) {
    mutable_focused_subcandidate_list()->MoveFirst();
  }
  return true;
}

CandidateList *CandidateList::mutable_focused_subcandidate_list() {
  CHECK(focused_candidate().IsSubcandidateList());
  return (*candidates_)[focused_index_]->mutable_subcandidate_list();
}

bool CandidateList::IsFirst(const size_t index) const {
  return (index == 0);
}

bool CandidateList::IsLast(const size_t index) const {
  return (index == size() - 1);
}

bool CandidateList::IsFirstPage(const size_t index) const {
  return (index < page_size_);
}

bool CandidateList::IsLastPage(const size_t index) const {
  size_t begin = 0;
  size_t end = 0;
  GetPageRange(index, &begin, &end);
  return end == last_index();
}

}  // namespace session
}  // namespace mozc
