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

#include "composer/internal/composition.h"

#include "base/logging.h"
#include "base/util.h"
#include "composer/internal/char_chunk.h"
#include "composer/internal/composition_input.h"
#include "composer/internal/transliterators.h"
#include "composer/table.h"

namespace mozc {
namespace composer {

Composition::Composition(const Table *table)
    : table_(table), input_t12r_(Transliterators::CONVERSION_STRING) {}

Composition::~Composition() {
  Erase();
}

void Composition::Erase() {
  CharChunkList::iterator it;
  for (it = chunks_.begin(); it != chunks_.end(); ++it) {
    delete *it;
  }
  chunks_.clear();
}

size_t Composition::InsertAt(size_t pos, const string &input) {
  CompositionInput composition_input;
  composition_input.set_raw(input);
  return InsertInput(pos, composition_input);
}

size_t Composition::InsertKeyAndPreeditAt(const size_t pos,
                                          const string &key,
                                          const string &preedit) {
  CompositionInput composition_input;
  composition_input.set_raw(key);
  composition_input.set_conversion(preedit);
  return InsertInput(pos, composition_input);
}

size_t Composition::InsertInput(size_t pos, const CompositionInput &input) {
  if (input.Empty()) {
    return pos;
  }

  CharChunkList::iterator right_chunk;
  MaybeSplitChunkAt(pos, &right_chunk);

  CharChunkList::iterator left_chunk = GetInsertionChunk(&right_chunk);
  CombinePendingChunks(left_chunk, input);

  CompositionInput mutable_input;
  mutable_input.CopyFrom(input);
  while (true) {
    (*left_chunk)->AddCompositionInput(&mutable_input);
    if (mutable_input.Empty()) {
      break;
    }
    left_chunk = InsertChunk(&right_chunk);
    mutable_input.set_is_new_input(false);
  }

  return GetPosition(Transliterators::LOCAL, right_chunk);
}

// Deletes a right-hand character of the composition.
size_t Composition::DeleteAt(const size_t position) {
  CharChunkList::iterator chunk_it;
  const size_t original_size = GetLength();
  size_t new_position = position;
  // We have to perform deletion repeatedly because there might be 0-length
  // chunk.
  // For example,
  // chunk0 : '{a}'  (invisible character only == 0-length)
  // chunk1 : 'b'
  // And DeleteAt(0) is invoked, we have to delete both chunks.
  while (!chunks_.empty() && GetLength() == original_size) {
    MaybeSplitChunkAt(position, &chunk_it);
    new_position = GetPosition(Transliterators::LOCAL, chunk_it);
    if (chunk_it == chunks_.end()) {
      break;
    }

    // We have to consider 0-length chunk.
    // If a chunk contains only invisible characters,
    // the result of GetLength is 0.
    if ((*chunk_it)->GetLength(Transliterators::LOCAL) <= 1) {
      delete *chunk_it;
      chunks_.erase(chunk_it);
      continue;
    }

    CharChunk *left_deleted_chunk_ptr = NULL;
    (*chunk_it)->SplitChunk(Transliterators::LOCAL, 1, &left_deleted_chunk_ptr);
    scoped_ptr<CharChunk> left_deleted_chunk(left_deleted_chunk_ptr);
  }
  return new_position;
}

size_t Composition::ConvertPosition(
    const size_t position_from,
    Transliterators::Transliterator transliterator_from,
    Transliterators::Transliterator transliterator_to) {
  // TODO(komatsu) This is a hacky way.
  if (transliterator_from == transliterator_to) {
    return position_from;
  }

  CharChunkList::iterator chunk_it;
  size_t inner_position_from;
  GetChunkAt(position_from, transliterator_from,
             &chunk_it, &inner_position_from);

  // No chunk was found, return 0 as a fallback.
  if (chunk_it == chunks_.end()) {
    return 0;
  }

  const size_t chunk_length_from = (*chunk_it)->GetLength(transliterator_from);

  CHECK(inner_position_from <= chunk_length_from);

  const size_t position_to = GetPosition(transliterator_to, chunk_it);

  if (inner_position_from == 0) {
    return position_to;
  }

  const size_t chunk_length_to = (*chunk_it)->GetLength(transliterator_to);
  if (inner_position_from == chunk_length_from) {
    // If the inner_position_from is the end of the chunk (ex. "ka|"
    // vs "か"), the converterd position should be the end of the
    // chunk too (ie. "か|").
    return position_to + chunk_length_to;
  }


  if (inner_position_from > chunk_length_to) {
    // When inner_position_from is greater than chunk_length_to
    // (ex. "ts|u" vs "つ", inner_position_from is 2 and
    // chunk_length_to is 1), the converted position should be the end
    // of the chunk (ie. "つ|").
    return position_to + chunk_length_to;
  }

  DCHECK(inner_position_from <= chunk_length_to);
  // When inner_position_from is less than or equal to chunk_length_to
  // (ex. "っ|と" vs "tto", inner_position_from is 1 and
  // chunk_length_to is 2), the converted position is adjusted from
  // the beginning of the chunk (ie. "t|to").
  return position_to + inner_position_from;
}

size_t Composition::SetDisplayMode(
    const size_t position,
    Transliterators::Transliterator transliterator) {
  SetTransliterator(0, GetLength(), transliterator);
  SetInputMode(transliterator);
  return GetLength();
}

void Composition::SetTransliterator(
    const size_t position_from,
    const size_t position_to,
    Transliterators::Transliterator transliterator) {
  if (position_from > position_to) {
    LOG(ERROR) << "position_from should not be greater than position_to.";
    return;
  }

  if (chunks_.empty()) {
    return;
  }

  CharChunkList::iterator chunk_it;
  size_t inner_position_from;
  GetChunkAt(position_from, Transliterators::LOCAL, &chunk_it,
             &inner_position_from);

  CharChunkList::iterator end_it;
  size_t inner_position_to;
  GetChunkAt(position_to, Transliterators::LOCAL, &end_it, &inner_position_to);

  // chunk_it and end_it can be the same iterator from the beginning.
  while (chunk_it != end_it) {
    (*chunk_it)->SetTransliterator(transliterator);
    ++chunk_it;
  }
  (*end_it)->SetTransliterator(transliterator);
}

Transliterators::Transliterator
Composition::GetTransliterator(size_t position) {
  // Due to GetChunkAt is not a const funcion, this function cannot be
  // a const function.
  CharChunkList::iterator chunk_it;
  size_t inner_position;
  GetChunkAt(position, Transliterators::LOCAL, &chunk_it, &inner_position);
  return (*chunk_it)->GetTransliterator(Transliterators::LOCAL);
}

size_t Composition::GetLength() const {
  return GetPosition(Transliterators::LOCAL, chunks_.end());
}

void Composition::GetStringWithModes(
    Transliterators::Transliterator transliterator,
    const TrimMode trim_mode,
    string* composition) const {
  composition->clear();
  if (chunks_.empty()) {
    // This is not an error. For example, the composition should be empty for
    // the first keydown event after turning on the IME.
    DCHECK(composition->empty()) << "An empty string should be returned.";
    return;
  }

  CharChunkList::const_iterator it;
  for (it = chunks_.begin(); *it != chunks_.back(); ++it) {
    (*it)->AppendResult(transliterator, composition);
  }

  switch (trim_mode) {
    case TRIM:
      (*it)->AppendTrimedResult(transliterator, composition);
      break;
    case ASIS:
      (*it)->AppendResult(transliterator, composition);
      break;
    case FIX:
      (*it)->AppendFixedResult(transliterator, composition);
      break;
    default:
      LOG(WARNING) << "Unexpected trim mode: " << trim_mode;
      break;
  }
}

void Composition::GetExpandedStrings(string *base,
                                     set<string> *expanded) const {
  GetExpandedStringsWithTransliterator(Transliterators::LOCAL, base, expanded);
}

void Composition::GetExpandedStringsWithTransliterator(
    Transliterators::Transliterator transliterator,
    string *base,
    set<string> *expanded) const {
  DCHECK(base);
  DCHECK(expanded);
  base->clear();
  expanded->clear();
  if (chunks_.empty()) {
    VLOG(1) << "The composition size is zero.";
    return;
  }

  CharChunkList::const_iterator it;
  for (it = chunks_.begin(); (*it) != chunks_.back(); ++it) {
    (*it)->AppendFixedResult(transliterator, base);
  }

  chunks_.back()->AppendTrimedResult(transliterator, base);
  // Get expanded from the last chunk
  chunks_.back()->GetExpandedResults(expanded);
}

void Composition::GetString(string *composition) const {
  composition->clear();
  if (chunks_.empty()) {
    VLOG(1) << "The composition size is zero.";
    return;
  }

  for (CharChunkList::const_iterator it = chunks_.begin();
       it != chunks_.end();
       ++it) {
    (*it)->AppendResult(Transliterators::LOCAL, composition);
  }
}

void Composition::GetStringWithTransliterator(
    Transliterators::Transliterator transliterator,
    string* output) const {
  GetStringWithModes(transliterator, FIX, output);
}

void Composition::GetStringWithTrimMode(const TrimMode trim_mode,
                                        string* output) const {
  GetStringWithModes(Transliterators::LOCAL, trim_mode, output);
}

void Composition::GetPreedit(
    size_t position, string *left, string *focused, string *right) const {
  string composition;
  GetString(&composition);
  left->assign(Util::SubString(composition, 0, position));
  focused->assign(Util::SubString(composition, position, 1));
  right->assign(Util::SubString(composition, position + 1, string::npos));
}

// This function is essentialy a const function, but chunks_.begin()
// violates the constness of this function.
void Composition::GetChunkAt(const size_t position,
                             Transliterators::Transliterator transliterator,
                             CharChunkList::iterator *chunk_it,
                             size_t *inner_position) {
  if (chunks_.empty()) {
    *inner_position = 0;
    *chunk_it = chunks_.begin();
    return;
  }

  size_t rest_pos = position;
  CharChunkList::iterator it;
  for (it = chunks_.begin(); it != chunks_.end(); ++it) {
    const size_t chunk_length = (*it)->GetLength(transliterator);
    if (rest_pos <= chunk_length) {
      *inner_position = rest_pos;
      *chunk_it = it;
      return;
    }
    rest_pos -= chunk_length;
  }
  *chunk_it = chunks_.end();
  --(*chunk_it);
  *inner_position = (**chunk_it)->GetLength(transliterator);
}

size_t Composition::GetPosition(
    Transliterators::Transliterator transliterator,
    const CharChunkList::const_iterator &cur_it) const {
  size_t position = 0;
  CharChunkList::const_iterator it;
  for (it = chunks_.begin(); it != cur_it; ++it) {
    position += (*it)->GetLength(transliterator);
  }
  return position;
}

// Return the left CharChunk and the right it.
CharChunk *Composition::MaybeSplitChunkAt(const size_t pos,
                                          CharChunkList::iterator *it) {
  // The position is the beginning of composition.
  if (pos <= 0) {
    *it = chunks_.begin();
    return NULL;
  }

  size_t inner_position;
  GetChunkAt(pos, Transliterators::LOCAL, it, &inner_position);

  CharChunk *chunk = **it;
  if (inner_position == chunk->GetLength(Transliterators::LOCAL)) {
    ++(*it);
    return chunk;
  }

  CharChunk *left_chunk = NULL;
  chunk->SplitChunk(Transliterators::LOCAL, inner_position, &left_chunk);
  chunks_.insert(*it, left_chunk);
  return left_chunk;
}

void Composition::CombinePendingChunks(
    CharChunkList::iterator it, const CompositionInput &input) {
  // Combine |**it| and |**(--it)| into |**it| as long as possible.
  const string &next_input =
    input.has_conversion() ? input.conversion() : input.raw();

  while (it != chunks_.begin()) {
    CharChunkList::iterator left_it = it;
    --left_it;
    if (!(*left_it)->IsConvertible(
            input_t12r_, table_, (*it)->pending() + next_input)) {
      return;
    }

    (*it)->Combine(**left_it);
    delete *left_it;
    chunks_.erase(left_it);
  }
}

// Insert a chunk to the prev of it.
CharChunkList::iterator Composition::InsertChunk(CharChunkList::iterator *it) {
  CharChunk *new_chunk = new CharChunk(input_t12r_, table_);
  return chunks_.insert(*it, new_chunk);
}

const CharChunkList &Composition::GetCharChunkList() const {
  return chunks_;
}

bool Composition::ShouldCommit() const {
  for (CharChunkList::const_iterator it = chunks_.begin();
       it != chunks_.end();
       ++it) {
    if (!(*it)->ShouldCommit()) {
      return false;
    }
  }
  return true;
}

CompositionInterface *Composition::Clone() const {
  return CloneImpl();
}

Composition *Composition::CloneImpl() const {
  Composition *object = new Composition(table_);

  // TODO(hsumita): Implements TableFactory and TransliteratorFactory and uses
  // it instead of copying pointers.
  object->input_t12r_ = input_t12r_;
  object->table_ = table_;

  for (CharChunkList::const_iterator it = chunks_.begin();
       it != chunks_.end(); ++it) {
    object->chunks_.push_back((*it)->Clone());
  }

  return object;
}

// Return charchunk to be inserted and iterator of the *next* char chunk.
CharChunkList::iterator Composition::GetInsertionChunk(
    CharChunkList::iterator *it) {
  if (*it == chunks_.begin()) {
    return InsertChunk(it);
  }

  CharChunkList::iterator left_it = *it;
  --left_it;
  if ((*left_it)->IsAppendable(input_t12r_, table_)) {
    return left_it;
  }
  return InsertChunk(it);
}

void Composition::SetInputMode(Transliterators::Transliterator transliterator) {
  input_t12r_ = transliterator;
}

void Composition::SetTable(const Table *table) {
  table_ = table;
}

}  // namespace composer
}  // namespace mozc
