// 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 "dictionary/user_dictionary_session.h"

#include <algorithm>

#include "base/logging.h"
#include "base/port.h"
#include "base/protobuf/protobuf.h"
#include "base/protobuf/repeated_field.h"
#include "dictionary/user_dictionary_importer.h"
#include "dictionary/user_dictionary_storage.h"
#include "dictionary/user_dictionary_storage.pb.h"
#include "dictionary/user_dictionary_util.h"

namespace mozc {
namespace user_dictionary {

using ::mozc::protobuf::RepeatedPtrField;

class UserDictionarySession::UndoCommand {
 public:
  virtual ~UndoCommand() {
  }
  virtual bool RunUndo(mozc::UserDictionaryStorage *storage) = 0;

 protected:
  UndoCommand() {
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(UndoCommand);
};

namespace {
// Implement "undo commands" for each operations.

class UndoCreateDictionaryCommand : public UserDictionarySession::UndoCommand {
 public:
  UndoCreateDictionaryCommand() {
  }

  virtual bool RunUndo(mozc::UserDictionaryStorage *storage) {
    if (storage->dictionaries_size() == 0) {
      return false;
    }

    storage->mutable_dictionaries()->RemoveLast();
    return true;
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(UndoCreateDictionaryCommand);
};

class UndoDeleteDictionaryCommand : public UserDictionarySession::UndoCommand {
 public:
  // This instance takes the ownership of the given dictionary.
  UndoDeleteDictionaryCommand(int index, UserDictionary *dictionary)
      : index_(index), dictionary_(dictionary) {
  }

  virtual bool RunUndo(mozc::UserDictionaryStorage *storage) {
    if (dictionary_.get() == NULL) {
      return false;
    }

    RepeatedPtrField<UserDictionary> *dictionaries =
        storage->mutable_dictionaries();
    dictionaries->AddAllocated(dictionary_.release());

    // Adjust the position of the reverted dictionary.
    rotate(dictionaries->pointer_begin() + index_,
           dictionaries->pointer_end() - 1,
           dictionaries->pointer_end());
    return true;
  }

 private:
  int index_;
  scoped_ptr<UserDictionary> dictionary_;

  DISALLOW_COPY_AND_ASSIGN(UndoDeleteDictionaryCommand);
};

class UndoDeleteDictionaryWithEnsuringNonEmptyStorageCommand
    : public UserDictionarySession::UndoCommand {
 public:
  // This instance takes the ownership of the given dictionary.
  explicit UndoDeleteDictionaryWithEnsuringNonEmptyStorageCommand(
      UserDictionary *dictionary)
      : dictionary_(dictionary) {
  }

  virtual bool RunUndo(mozc::UserDictionaryStorage *storage) {
    if (storage->dictionaries_size() != 1) {
      return false;
    }
    dictionary_->Swap(storage->mutable_dictionaries(0));
    return true;
  }

 private:
  scoped_ptr<UserDictionary> dictionary_;

  DISALLOW_COPY_AND_ASSIGN(
      UndoDeleteDictionaryWithEnsuringNonEmptyStorageCommand);
};

class UndoRenameDictionaryCommand : public UserDictionarySession::UndoCommand {
 public:
  UndoRenameDictionaryCommand(
      uint64 dictionary_id, const string &original_name)
      : dictionary_id_(dictionary_id), original_name_(original_name) {
  }

  virtual bool RunUndo(mozc::UserDictionaryStorage *storage) {
    UserDictionary *dictionary =
        UserDictionaryUtil::GetMutableUserDictionaryById(
            storage, dictionary_id_);
    if (dictionary == NULL) {
      return false;
    }

    dictionary->set_name(original_name_);
    return true;
  }

 private:
  uint64 dictionary_id_;
  string original_name_;

  DISALLOW_COPY_AND_ASSIGN(UndoRenameDictionaryCommand);
};

class UndoAddEntryCommand : public UserDictionarySession::UndoCommand {
 public:
  explicit UndoAddEntryCommand(uint64 dictionary_id)
      : dictionary_id_(dictionary_id) {
  }

  virtual bool RunUndo(mozc::UserDictionaryStorage *storage) {
    UserDictionary *dictionary =
        UserDictionaryUtil::GetMutableUserDictionaryById(
            storage, dictionary_id_);
    if (dictionary == NULL || dictionary->entries_size() == 0) {
      return false;
    }

    dictionary->mutable_entries()->RemoveLast();
    return true;
  }

 private:
  uint64 dictionary_id_;

  DISALLOW_COPY_AND_ASSIGN(UndoAddEntryCommand);
};

class UndoEditEntryCommand : public UserDictionarySession::UndoCommand {
 public:
  UndoEditEntryCommand(uint64 dictionary_id, int index,
                       const UserDictionary::Entry &original_entry)
      : dictionary_id_(dictionary_id), index_(index),
        original_entry_(original_entry) {
  }

  virtual bool RunUndo(mozc::UserDictionaryStorage *storage) {
    UserDictionary *dictionary =
        UserDictionaryUtil::GetMutableUserDictionaryById(
            storage, dictionary_id_);
    if (dictionary == NULL ||
        index_ < 0 || dictionary->entries_size() <= index_) {
      return false;
    }

    dictionary->mutable_entries(index_)->CopyFrom(original_entry_);
    return true;
  }

 private:
  uint64 dictionary_id_;
  int index_;
  UserDictionary::Entry original_entry_;

  DISALLOW_COPY_AND_ASSIGN(UndoEditEntryCommand);
};

struct DeleteEntryComparator {
  bool operator()(const pair<int, UserDictionary::Entry*> &entry1,
                  const pair<int, UserDictionary::Entry*> &entry2) {
    return entry1.first < entry2.first;
  }
};

class UndoDeleteEntryCommand : public UserDictionarySession::UndoCommand {
 public:
  // This instance takes the ownership of the given entries.
  UndoDeleteEntryCommand(
      uint64 dictionary_id,
      const vector<pair<int, UserDictionary::Entry*> > deleted_entries)
      : dictionary_id_(dictionary_id), deleted_entries_(deleted_entries) {
    sort(deleted_entries_.begin(), deleted_entries_.end(),
         DeleteEntryComparator());
  }
  virtual ~UndoDeleteEntryCommand() {
    for (size_t i = 0; i < deleted_entries_.size(); ++i) {
      delete deleted_entries_[i].second;
    }
  }

  virtual bool RunUndo(mozc::UserDictionaryStorage *storage) {
    UserDictionary *dictionary =
        UserDictionaryUtil::GetMutableUserDictionaryById(
            storage, dictionary_id_);
    if (dictionary == NULL) {
      return false;
    }

    // Check validity of the holding indices.
    const int num_merged_entries =
        dictionary->entries_size() + deleted_entries_.size();
    for (size_t i = 0; i < deleted_entries_.size(); ++i) {
      const int index = deleted_entries_[i].first;
      if (index < 0 || num_merged_entries <= index) {
        return false;
      }
    }

    RepeatedPtrField<UserDictionary::Entry> *entries =
        dictionary->mutable_entries();

    // Move instances to backup vector.
    vector<UserDictionary::Entry*> backup(
        entries->pointer_begin(), entries->pointer_end());
    while (entries->size() > 0) {
      entries->ReleaseLast();
    }

    // Merge two vectors into entries.
    int backup_index = 0;
    int deleted_entry_index = 0;
    for (int index = 0; deleted_entry_index < deleted_entries_.size();
         ++index) {
      if (index == deleted_entries_[deleted_entry_index].first) {
        entries->AddAllocated(deleted_entries_[deleted_entry_index].second);
        ++deleted_entry_index;
      } else {
        entries->AddAllocated(backup[backup_index]);
        ++backup_index;
      }
    }

    // Add remaining entries in backup to the entries.
    for (; backup_index < backup.size(); ++backup_index) {
      entries->AddAllocated(backup[backup_index]);
    }

    // Release the entries.
    deleted_entries_.clear();
    return true;
  }

 private:
  uint64 dictionary_id_;
  vector<pair<int, UserDictionary::Entry*> > deleted_entries_;

  DISALLOW_COPY_AND_ASSIGN(UndoDeleteEntryCommand);
};

class UndoImportFromStringCommand : public UserDictionarySession::UndoCommand {
 public:
  UndoImportFromStringCommand(uint64 dictionary_id, int original_num_entries)
      : dictionary_id_(dictionary_id),
        original_num_entries_(original_num_entries) {
  }

  virtual bool RunUndo(mozc::UserDictionaryStorage *storage) {
    UserDictionary *dictionary =
        UserDictionaryUtil::GetMutableUserDictionaryById(
            storage, dictionary_id_);
    if (dictionary == NULL) {
      return false;
    }

    RepeatedPtrField<UserDictionary::Entry> *entries =
        dictionary->mutable_entries();
    while (original_num_entries_ < entries->size()) {
      entries->RemoveLast();
    }
    return true;
  }

 private:
  uint64 dictionary_id_;
  int original_num_entries_;

  DISALLOW_COPY_AND_ASSIGN(UndoImportFromStringCommand);
};

// The limit of the number of commands remembered by the session for undo.
const int kMaxUndoHistory = 30;

// The default name of a dictionary, which is created to ensure "non-empty"
// storage.
const char kDefaultDictionaryName[] = "user dictionary";

}  // namespace

UserDictionarySession::UserDictionarySession(const string &filepath)
    : storage_(new mozc::UserDictionaryStorage(filepath)),
      default_dictionary_name_(kDefaultDictionaryName) {
}
UserDictionarySession::~UserDictionarySession() {
  ClearUndoHistory();
}

// TODO(hidehiko) move this to header.
const UserDictionaryStorage &UserDictionarySession::storage() const {
  return *storage_;
}
mozc::UserDictionaryStorage *UserDictionarySession::mutable_storage() {
  return storage_.get();
}

UserDictionaryCommandStatus::Status
UserDictionarySession::SetDefaultDictionaryName(
    const string &dictionary_name) {
  // Validate the name for the default dictionary. The name is used to create
  // a dictionary "for an empty storage", so check the validity with the
  // default instance of UserDictionaryStorage.
  UserDictionaryCommandStatus::Status status =
      UserDictionaryUtil::ValidateDictionaryName(
          UserDictionaryStorage::default_instance(), dictionary_name);
  if (status == UserDictionaryCommandStatus::USER_DICTIONARY_COMMAND_SUCCESS) {
    default_dictionary_name_ = dictionary_name;
  }
  return status;
}

UserDictionaryCommandStatus::Status UserDictionarySession::Load() {
  return LoadInternal(false);
}

UserDictionaryCommandStatus::Status
UserDictionarySession::LoadWithEnsuringNonEmptyStorage() {
  return LoadInternal(true);
}

UserDictionaryCommandStatus::Status UserDictionarySession::LoadInternal(
    bool ensure_non_empty_storage) {
  UserDictionaryCommandStatus::Status status;
  if (storage_->Load()) {
    status = UserDictionaryCommandStatus::USER_DICTIONARY_COMMAND_SUCCESS;
  } else {
    switch (storage_->GetLastError()) {
      case mozc::UserDictionaryStorage::FILE_NOT_EXISTS:
        status = UserDictionaryCommandStatus::FILE_NOT_FOUND;
        break;
      case mozc::UserDictionaryStorage::BROKEN_FILE:
        status = UserDictionaryCommandStatus::INVALID_FILE_FORMAT;
        break;
      default:
        LOG(ERROR) << "Unknown error code: " << storage_->GetLastError();
        status = UserDictionaryCommandStatus::UNKNOWN_ERROR;
        break;
    }
  }

  if ((ensure_non_empty_storage && EnsureNonEmptyStorage()) ||
      status == UserDictionaryCommandStatus::USER_DICTIONARY_COMMAND_SUCCESS) {
    // If the storage is updated, clear the undo history.
    ClearUndoHistory();
  }
  return status;
}

namespace {
// Locker of mozc::UserDictionaryStorage in RAII idiom.
class ScopedUserDictionaryLocker {
 public:
  explicit ScopedUserDictionaryLocker(mozc::UserDictionaryStorage *storage)
      : storage_(storage) {
    is_locked_ = storage_->Lock();
  }
  ~ScopedUserDictionaryLocker() {
    if (is_locked_) {
      storage_->UnLock();
    }
  }

  bool is_locked() const { return is_locked_; }
 private:
  mozc::UserDictionaryStorage *storage_;
  bool is_locked_;

  DISALLOW_COPY_AND_ASSIGN(ScopedUserDictionaryLocker);
};
}  // namespace

UserDictionaryCommandStatus::Status UserDictionarySession::Save() {
  ScopedUserDictionaryLocker locker(storage_.get());
  if (!locker.is_locked()) {
    LOG(ERROR) << "Failed to take a lock.";
    return UserDictionaryCommandStatus::UNKNOWN_ERROR;
  }

  if (!storage_->Save()) {
    switch (storage_->GetLastError()) {
      case mozc::UserDictionaryStorage::TOO_BIG_FILE_BYTES:
        return UserDictionaryCommandStatus::FILE_SIZE_LIMIT_EXCEEDED;
        // TODO(hidehiko): Handle SYNC_FAILURE.
      default:
        LOG(ERROR) << "Unknown error code: " << storage_->GetLastError();
        return UserDictionaryCommandStatus::UNKNOWN_ERROR;
    }
    // Should never reach here.
  }

  return UserDictionaryCommandStatus::USER_DICTIONARY_COMMAND_SUCCESS;
}

UserDictionaryCommandStatus::Status UserDictionarySession::Undo() {
  if (undo_history_.empty()) {
    return UserDictionaryCommandStatus::NO_UNDO_HISTORY;
  }

  scoped_ptr<UndoCommand> undo_command(undo_history_.back());
  undo_history_.pop_back();
  return undo_command->RunUndo(storage_.get()) ?
      UserDictionaryCommandStatus::USER_DICTIONARY_COMMAND_SUCCESS :
      UserDictionaryCommandStatus::UNKNOWN_ERROR;
}

UserDictionaryCommandStatus::Status UserDictionarySession::CreateDictionary(
    const string &dictionary_name, uint64 *new_dictionary_id) {
  UserDictionaryCommandStatus::Status status =
      UserDictionaryUtil::CreateDictionary(
          storage_.get(), dictionary_name, new_dictionary_id);
  if (status == UserDictionaryCommandStatus::USER_DICTIONARY_COMMAND_SUCCESS) {
    AddUndoCommand(new UndoCreateDictionaryCommand);
  }
  return status;
}

UserDictionaryCommandStatus::Status UserDictionarySession::DeleteDictionary(
    uint64 dictionary_id) {
  return DeleteDictionaryInternal(dictionary_id, false);
}

UserDictionaryCommandStatus::Status
UserDictionarySession::DeleteDictionaryWithEnsuringNonEmptyStorage(
    uint64 dictionary_id) {
  return DeleteDictionaryInternal(dictionary_id, true);
}

UserDictionaryCommandStatus::Status
UserDictionarySession::DeleteDictionaryInternal(
    uint64 dictionary_id, bool ensure_non_empty_storage) {
  int original_index;
  UserDictionary *deleted_dictionary;
  if (!UserDictionaryUtil::DeleteDictionary(
          storage_.get(), dictionary_id,
          &original_index, &deleted_dictionary)) {
    // Failed to delete the dictionary.
    return UserDictionaryCommandStatus::UNKNOWN_DICTIONARY_ID;
  }

  if ((ensure_non_empty_storage && EnsureNonEmptyStorage())) {
    // The storage was empty.
    AddUndoCommand(new UndoDeleteDictionaryWithEnsuringNonEmptyStorageCommand(
        deleted_dictionary));
  } else {
    AddUndoCommand(
        new UndoDeleteDictionaryCommand(original_index, deleted_dictionary));
  }

  return UserDictionaryCommandStatus::USER_DICTIONARY_COMMAND_SUCCESS;
}

UserDictionaryCommandStatus::Status UserDictionarySession::RenameDictionary(
    uint64 dictionary_id, const string &dictionary_name) {
  string original_name;
  const UserDictionary *dictionary =
      UserDictionaryUtil::GetUserDictionaryById(*storage_, dictionary_id);
  if (dictionary != NULL) {
    // Note that if dictionary is null, it means the dictionary_id is invalid
    // so following RenameDictionary will fail, and error handling is done
    // in the following codes.
    original_name = dictionary->name();
  }

  if (!storage_->RenameDictionary(dictionary_id, dictionary_name)) {
    switch (storage_->GetLastError()) {
      case mozc::UserDictionaryStorage::EMPTY_DICTIONARY_NAME:
        return UserDictionaryCommandStatus::DICTIONARY_NAME_EMPTY;
      case mozc::UserDictionaryStorage::TOO_LONG_DICTIONARY_NAME:
        return UserDictionaryCommandStatus::DICTIONARY_NAME_TOO_LONG;
      case mozc::UserDictionaryStorage::INVALID_CHARACTERS_IN_DICTIONARY_NAME:
        return UserDictionaryCommandStatus
            ::DICTIONARY_NAME_CONTAINS_INVALID_CHARACTER;
      case mozc::UserDictionaryStorage::DUPLICATED_DICTIONARY_NAME:
        return UserDictionaryCommandStatus::DICTIONARY_NAME_DUPLICATED;
      case mozc::UserDictionaryStorage::INVALID_DICTIONARY_ID:
        return UserDictionaryCommandStatus::UNKNOWN_DICTIONARY_ID;
      default:
        LOG(ERROR) << "Unknown error code: " << storage_->GetLastError();
        return UserDictionaryCommandStatus::UNKNOWN_ERROR;
    }
    // Should never reach here.
  }

  AddUndoCommand(
      new UndoRenameDictionaryCommand(dictionary_id, original_name));
  return UserDictionaryCommandStatus::USER_DICTIONARY_COMMAND_SUCCESS;
}

UserDictionaryCommandStatus::Status UserDictionarySession::AddEntry(
    uint64 dictionary_id, const UserDictionary::Entry &entry) {
  UserDictionary *dictionary =
      UserDictionaryUtil::GetMutableUserDictionaryById(
          storage_.get(), dictionary_id);
  if (dictionary == NULL) {
    return UserDictionaryCommandStatus::UNKNOWN_DICTIONARY_ID;
  }

  if (UserDictionaryUtil::IsDictionaryFull(*dictionary)) {
    return UserDictionaryCommandStatus::ENTRY_SIZE_LIMIT_EXCEEDED;
  }

  const UserDictionaryCommandStatus::Status status =
      UserDictionaryUtil::ValidateEntry(entry);
  if (status != UserDictionaryCommandStatus::USER_DICTIONARY_COMMAND_SUCCESS) {
    // Invalid entry.
    return status;
  }

  UserDictionary::Entry *new_entry = dictionary->add_entries();
  new_entry->CopyFrom(entry);
  UserDictionaryUtil::SanitizeEntry(new_entry);

  AddUndoCommand(new UndoAddEntryCommand(dictionary_id));
  return UserDictionaryCommandStatus::USER_DICTIONARY_COMMAND_SUCCESS;
}

UserDictionaryCommandStatus::Status UserDictionarySession::EditEntry(
    uint64 dictionary_id, int index, const UserDictionary::Entry &entry) {
  UserDictionary *dictionary =
      UserDictionaryUtil::GetMutableUserDictionaryById(
          storage_.get(), dictionary_id);
  if (dictionary == NULL) {
    return UserDictionaryCommandStatus::UNKNOWN_DICTIONARY_ID;
  }

  if (index < 0 || dictionary->entries_size() <= index) {
    return UserDictionaryCommandStatus::ENTRY_INDEX_OUT_OF_RANGE;
  }

  const UserDictionaryCommandStatus::Status status =
      UserDictionaryUtil::ValidateEntry(entry);
  if (status != UserDictionaryCommandStatus::USER_DICTIONARY_COMMAND_SUCCESS) {
    // Invalid entry.
    return status;
  }

  UserDictionary::Entry *target_entry = dictionary->mutable_entries(index);
  AddUndoCommand(
      new UndoEditEntryCommand(dictionary_id, index, *target_entry));

  target_entry->CopyFrom(entry);
  UserDictionaryUtil::SanitizeEntry(target_entry);
  return UserDictionaryCommandStatus::USER_DICTIONARY_COMMAND_SUCCESS;
}

UserDictionaryCommandStatus::Status UserDictionarySession::DeleteEntry(
    uint64 dictionary_id, const vector<int> &index_list) {
  UserDictionary *dictionary =
      UserDictionaryUtil::GetMutableUserDictionaryById(
          storage_.get(), dictionary_id);
  if (dictionary == NULL) {
    return UserDictionaryCommandStatus::UNKNOWN_DICTIONARY_ID;
  }

  for (size_t i = 0; i < index_list.size(); ++i) {
    const int index = index_list[i];
    if (index < 0 || dictionary->entries_size() <= index) {
      return UserDictionaryCommandStatus::ENTRY_INDEX_OUT_OF_RANGE;
    }
  }

  vector<pair<int, UserDictionary::Entry*> > deleted_entries;
  deleted_entries.reserve(index_list.size());

  RepeatedPtrField<UserDictionary::Entry> *entries =
      dictionary->mutable_entries();
  UserDictionary::Entry **data = entries->mutable_data();
  for (size_t i = 0; i < index_list.size(); ++i) {
    const int index = index_list[i];

    deleted_entries.push_back(make_pair(index, data[index]));
    data[index] = NULL;
  }

  UserDictionary::Entry **tail = remove(
      data, data + entries->size(), static_cast<UserDictionary::Entry*>(NULL));
  const int remaining_size = tail - data;
  while (entries->size() > remaining_size) {
    entries->ReleaseLast();
  }

  AddUndoCommand(new UndoDeleteEntryCommand(dictionary_id, deleted_entries));
  return UserDictionaryCommandStatus::USER_DICTIONARY_COMMAND_SUCCESS;
}

UserDictionaryCommandStatus::Status UserDictionarySession::ImportFromString(
    uint64 dictionary_id, const string &data) {
  UserDictionary *dictionary =
      UserDictionaryUtil::GetMutableUserDictionaryById(
          storage_.get(), dictionary_id);
  if (dictionary == NULL) {
    return UserDictionaryCommandStatus::UNKNOWN_DICTIONARY_ID;
  }

  int original_num_entries = dictionary->entries_size();
  UserDictionaryCommandStatus::Status status =
      ImportFromStringInternal(dictionary, data);

  // Remember the command regardless of whether the importing is successfully
  // done or not, because ImportFromStringInternal updates the dictionary
  // always.
  AddUndoCommand(
      new UndoImportFromStringCommand(dictionary_id, original_num_entries));

  return status;
}

UserDictionaryCommandStatus::Status
UserDictionarySession::ImportFromStringInternal(
    UserDictionary* dictionary, const string &data) {
  UserDictionaryImporter::ErrorType import_result;
  {
    UserDictionaryImporter::StringTextLineIterator iter(data);
    import_result =
        UserDictionaryImporter::ImportFromTextLineIterator(
            UserDictionaryImporter::IME_AUTO_DETECT, &iter, dictionary);
  }

  LOG_IF(WARNING, import_result != UserDictionaryImporter::IMPORT_NO_ERROR)
      << "Import failed: " << import_result;

  // Return status code.
  switch (import_result) {
    case UserDictionaryImporter::IMPORT_NO_ERROR:
      // Succeeded.
      return UserDictionaryCommandStatus::USER_DICTIONARY_COMMAND_SUCCESS;

    // Failed on some reasons.
    case UserDictionaryImporter::IMPORT_TOO_MANY_WORDS:
      return UserDictionaryCommandStatus::IMPORT_TOO_MANY_WORDS;
    case UserDictionaryImporter::IMPORT_INVALID_ENTRIES:
      return UserDictionaryCommandStatus::IMPORT_INVALID_ENTRIES;
    default:
      LOG(ERROR) << "Unknown error: " << import_result;
      return UserDictionaryCommandStatus::UNKNOWN_ERROR;
  }
}

UserDictionaryCommandStatus::Status
UserDictionarySession::ImportToNewDictionaryFromString(
    const string &dictionary_name, const string &data,
    uint64 *new_dictionary_id) {
  UserDictionaryCommandStatus::Status status =
      UserDictionaryUtil::CreateDictionary(
          storage_.get(), dictionary_name, new_dictionary_id);
  if (status != UserDictionaryCommandStatus::USER_DICTIONARY_COMMAND_SUCCESS) {
    return status;
  }

  // We can use undo command for CreateDictionary here, too.
  AddUndoCommand(new UndoCreateDictionaryCommand);

  UserDictionary *dictionary =
      UserDictionaryUtil::GetMutableUserDictionaryById(
          storage_.get(), *new_dictionary_id);
  if (dictionary == NULL) {
    // The dictionary should be always found.
    return UserDictionaryCommandStatus::UNKNOWN_ERROR;
  }

  return ImportFromStringInternal(dictionary, data);
}

bool UserDictionarySession::EnsureNonEmptyStorage() {
  if (storage_->dictionaries_size() > 0) {
    // The storage already has at least one dictionary. Do nothing.
    return false;
  }

  // Creates a dictionary with the default name. Should never fail.
  uint64 new_dictionary_id;
  UserDictionaryCommandStatus::Status status =
      UserDictionaryUtil::CreateDictionary(
          storage_.get(), default_dictionary_name_, &new_dictionary_id);
  CHECK_EQ(
      status, UserDictionaryCommandStatus::USER_DICTIONARY_COMMAND_SUCCESS);
  return true;
}

void UserDictionarySession::ClearUndoHistory() {
  for (deque<UndoCommand *>::iterator iter = undo_history_.begin();
       iter != undo_history_.end(); ++iter) {
    delete *iter;
  }
  undo_history_.clear();
}

void UserDictionarySession::AddUndoCommand(UndoCommand *undo_command) {
  // To avoid OOM due to huge undo history, we limit the undo-able
  // command size by kMaxUndoHistory.
  while (undo_history_.size() >= kMaxUndoHistory) {
    delete undo_history_.front();
    undo_history_.pop_front();
  }

  undo_history_.push_back(undo_command);
}

}  // namespace user_dictionary
}  // namespace mozc
