// 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 "gui/dictionary_tool/dictionary_tool.h"

#include <QtCore/QTimer>
#include <QtGui/QtGui>
#include <QtGui/QProgressDialog>

#ifdef OS_WIN
#include <Windows.h>
#endif  // OS_WIN

#include <algorithm>
#include <functional>
#include <string>
#include <vector>

#include "base/file_stream.h"
#include "base/logging.h"
#include "base/run_level.h"
#include "base/util.h"
#include "client/client.h"
#include "data_manager/user_pos_manager.h"
#include "dictionary/user_dictionary_importer.h"
#include "dictionary/user_dictionary_session.h"
#include "dictionary/user_dictionary_storage.h"
#include "dictionary/user_dictionary_storage.pb.h"
#include "dictionary/user_dictionary_util.h"
#include "dictionary/user_pos.h"
#include "gui/base/win_util.h"
#include "gui/config_dialog/combobox_delegate.h"
#include "gui/dictionary_tool/find_dialog.h"
#include "gui/dictionary_tool/import_dialog.h"

namespace mozc {
namespace gui {

using mozc::user_dictionary::UserDictionary;
using mozc::user_dictionary::UserDictionaryCommandStatus;
using mozc::user_dictionary::UserDictionarySession;
using mozc::user_dictionary::UserDictionaryStorage;

namespace {

// set longer timeout because it takes longer time
// to reload all user dictionary.
const int kSessionTimeout = 100000;

int GetTableHeight(QTableWidget *widget) {
  // Dragon Hack:
  // Here we use "龍" to calc font size, as it looks almsot square
  // const char kHexBaseChar[]= "龍";
  const char kHexBaseChar[]= "\xE9\xBE\x8D";
  const QRect rect =
      QFontMetrics(widget->font()).boundingRect(
          QObject::trUtf8(kHexBaseChar));
  return static_cast<int>(rect.height() * 1.4);
}

QProgressDialog *CreateProgressDialog(
    QString message, QWidget *parent, int size) {
  QProgressDialog *progress =
      new QProgressDialog(message, "", 0, size, parent);
  CHECK(progress);
  progress->setWindowFlags(Qt::Window | Qt::CustomizeWindowHint);
  progress->setWindowModality(Qt::WindowModal);
  // This cancel button is invisible to users.
  // We don't accept any cancel operation
  QPushButton *cancel_button = new QPushButton;
  CHECK(cancel_button);
  progress->setAutoClose(true);
  progress->setCancelButton(cancel_button);
  progress->setFixedSize(QSize(400, 100));
  cancel_button->setVisible(false);

  return progress;
}

#if defined(OS_WIN) || defined(OS_MACOSX)
void InstallStyleSheet(const QString &filename) {
  QFile file(filename);
  file.open(QFile::ReadOnly);
  qApp->setStyleSheet(QLatin1String(file.readAll()));
}
#endif

// Use QTextStream to read UTF16 text -- we can't use ifstream,
// since ifstream cannot handle Wide character.
class UTF16TextLineIterator
    : public UserDictionaryImporter::TextLineIteratorInterface {
 public:
  UTF16TextLineIterator(
      UserDictionaryImporter::EncodingType encoding_type,
      const string &filename,
      const QString &message, QWidget *parent)
      : stream_(new QTextStream) {
    CHECK_EQ(UserDictionaryImporter::UTF16, encoding_type);
    file_.setFileName(QString::fromUtf8(filename.c_str()));
    if (!file_.open(QIODevice::ReadOnly)) {
      LOG(ERROR) << "Cannot open: " << filename;
    }
    stream_->setDevice(&file_);
    stream_->setCodec("UTF-16");
    progress_.reset(CreateProgressDialog(message, parent, file_.size()));
  }

  bool IsAvailable() const {
    return file_.error() == QFile::NoError;
  }

  bool Next(string *line) {
    if (stream_->atEnd()) {
      return false;
    }

    // Can't use ReadLine as ReadLine doesn't support CR only text.
    QChar ch;
    QString output_line;
    while (!stream_->atEnd()) {
      *(stream_.get()) >> ch;
      if (output_line.isEmpty() && ch == QLatin1Char('\n')) {
        // no harm to skip empty line
        continue;
      }
      if (ch == QLatin1Char('\n') || ch == QLatin1Char('\r')) {
        break;
      } else {
        output_line += ch;
      }
    }

    progress_->setValue(file_.pos());

    *line = output_line.toUtf8().data();
    return true;
  }

  void Reset() {
    file_.seek(0);
    stream_.reset(new QTextStream);
    stream_->setDevice(&file_);
    stream_->setCodec("UTF-16");
  }

 private:
  QFile file_;
  scoped_ptr<QTextStream> stream_;
  scoped_ptr<QProgressDialog> progress_;
};

class MultiByteTextLineIterator
    : public UserDictionaryImporter::TextLineIteratorInterface {
 public:
  MultiByteTextLineIterator(
      UserDictionaryImporter::EncodingType encoding_type,
      const string &filename,
      const QString &message, QWidget *parent)
      : encoding_type_(encoding_type),
        ifs_(new InputFileStream(filename.c_str())),
        first_line_(true) {
    const streampos begin = ifs_->tellg();
    ifs_->seekg(0, ios::end);
    const size_t size = static_cast<size_t>(ifs_->tellg() - begin);
    ifs_->seekg(0, ios::beg);
    progress_.reset(CreateProgressDialog(message, parent, size));
  }

  bool IsAvailable() const {
    // This means that neither failbit nor badbit is set.
    // TODO(yukawa): Consider to remove |ifs_->eof()|. Furthermore, we should
    // replace IsAvailable() with something easier to understand, e.g.,
    // Done() or HasNext().
    return ifs_->good() || ifs_->eof();
  }

  bool Next(string *line)  {
    if (!ifs_->good()) {
      return false;
    }

    // Can't use getline as getline doesn't support CR only text.
    char ch;
    string output_line;
    while (ifs_->good()) {
      ifs_->get(ch);
      if (output_line.empty() && ch == '\n') {
        continue;
      }
      if (ch == '\n' || ch == '\r') {
        break;
      } else {
        output_line += ch;
      }
    }

    progress_->setValue(ifs_->tellg());

    *line = output_line;

    // We can't use QTextCodec as QTextCodec is not enabled by default.
    // We won't enable it as it increases the binary size.
    if (encoding_type_ == UserDictionaryImporter::SHIFT_JIS) {
      const string input = *line;
      Util::SJISToUTF8(input, line);
    }

    // strip UTF8 BOM
    if (first_line_ &&
        encoding_type_ == UserDictionaryImporter::UTF8) {
      Util::StripUTF8BOM(line);
    }

    Util::ChopReturns(line);

    first_line_ = false;
    return true;
  }

  void Reset() {
    // Clear state bit (eofbit, failbit, badbit).
    ifs_->clear();
    ifs_->seekg(0, ios_base::beg);
    first_line_ = true;
  }

 private:
  UserDictionaryImporter::EncodingType encoding_type_;
  scoped_ptr<InputFileStream> ifs_;
  scoped_ptr<QProgressDialog> progress_;
  bool first_line_;
};

UserDictionaryImporter::TextLineIteratorInterface *CreateTextLineIterator(
    UserDictionaryImporter::EncodingType encoding_type,
    const string &filename,
    QWidget *parent) {
  if (encoding_type == UserDictionaryImporter::ENCODING_AUTO_DETECT) {
    encoding_type = UserDictionaryImporter::GuessFileEncodingType(filename);
  }

  if (encoding_type == UserDictionaryImporter::NUM_ENCODINGS) {
    LOG(ERROR) << "GuessFileEncodingType() returns UNKNOWN encoding.";
    // set default encoding
#ifdef OS_WIN
    encoding_type = UserDictionaryImporter::SHIFT_JIS;
#else
    encoding_type = UserDictionaryImporter::UTF16;
#endif
  }

  VLOG(1) << "Setting Encoding to: " << static_cast<int>(encoding_type);

  const QString message = QObject::tr("Importing new words...");

  switch (encoding_type) {
    case UserDictionaryImporter::UTF8:
    case UserDictionaryImporter::SHIFT_JIS:
      return new MultiByteTextLineIterator(encoding_type, filename,
                                           message, parent);
      break;
    case UserDictionaryImporter::UTF16:
      return new UTF16TextLineIterator(encoding_type, filename,
                                       message, parent);
      break;
    default:
      return NULL;
  }

  return NULL;
}
}  // namespace

DictionaryTool::DictionaryTool(QWidget *parent)
    : QMainWindow(parent),
      import_dialog_(NULL), find_dialog_(NULL),
      session_(new UserDictionarySession(
          UserDictionaryUtil::GetUserDictionaryFileName())),
      current_dic_id_(0), modified_(false), monitoring_user_edit_(false),
      window_title_(tr("Mozc")),
      dic_menu_(new QMenu),
      new_action_(NULL), rename_action_(NULL),
      delete_action_(NULL), find_action_(NULL),
      import_create_action_(NULL), import_append_action_(NULL),
      export_action_(NULL), import_default_ime_action_(NULL),
      client_(client::ClientFactory::NewClient()),
      is_available_(true),
      max_entry_size_(mozc::UserDictionaryStorage::max_entry_size()),
      user_pos_(new UserPOS(
          UserPosManager::GetUserPosManager()->GetUserPOSData())) {
  setupUi(this);

  // Create and set up ImportDialog object.
  import_dialog_ = new ImportDialog(this);

  // Create and set up FindDialog object.
  find_dialog_ = new FindDialog(this, dic_content_);

  client_->set_timeout(kSessionTimeout);

  if (session_->Load() !=
      UserDictionaryCommandStatus::USER_DICTIONARY_COMMAND_SUCCESS) {
    LOG(WARNING) << "UserDictionarySession::Load() failed";
  }

  if (!session_->mutable_storage()->Lock()) {
    QMessageBox::information(
        this, window_title_,
        tr("Another process is accessing the user dictionary file."));
    is_available_ = false;
    return;
  }

#ifndef ENABLE_CLOUD_SYNC
  if (session_->mutable_storage()
      ->ConvertSyncDictionariesToNormalDictionaries()) {
    LOG(INFO) << "Syncable dictionaries are converted to normal dictionaries";
    session_->mutable_storage()->Save();
  }
#endif  // !ENABLE_CLOUD_SYNC

  // main window
#ifndef OS_LINUX
  // For some reason setCentralWidget crashes the dictionary_tool on Linux
  // TODO(taku): investigate the cause of the crashes
  setCentralWidget(splitter_);
#endif

  setContextMenuPolicy(Qt::NoContextMenu);

  // toolbar
  dic_menu_button_ = new QPushButton(tr("Tools"), this);
  new_word_button_ = new QPushButton(tr("Add"), this);
  delete_word_button_ = new QPushButton(tr("Remove"), this);
  toolbar_->addWidget(dic_menu_button_);
  toolbar_->addWidget(new_word_button_);
  toolbar_->addWidget(delete_word_button_);

  // Cosmetic tweaks for Mac.
#ifdef OS_MACOSX
  dic_list_->setAttribute(Qt::WA_MacShowFocusRect, false);
  dic_list_->setAutoFillBackground(true);
  dic_list_->setFrameStyle(QFrame::NoFrame);

  dic_content_->setFrameStyle(QFrame::NoFrame);
  dic_content_->setShowGrid(false);
#endif

  dic_content_->setWordWrap(false);
  dic_content_->verticalHeader()->hide();
  dic_content_->horizontalHeader()->setStretchLastSection(true);
  dic_content_->horizontalHeader()->setSortIndicatorShown(true);
  dic_content_->horizontalHeader()->setHighlightSections(false);
  dic_content_->setAlternatingRowColors(true);

  // We fix the row height so that paint() is executed faster.
  // This changes allows DictionaryTool handle about 1M words.
  dic_content_->verticalHeader()->setResizeMode(QHeaderView::Fixed);
  dic_content_->verticalHeader()->setDefaultSectionSize(
      GetTableHeight(dic_content_));

  // Get a list of POS and set a custom delagate that holds the list.
  vector<string> tmp_pos_vec;
  user_pos_->GetPOSList(&tmp_pos_vec);
  QStringList pos_list;
  for (size_t i = 0; i < tmp_pos_vec.size(); ++i) {
    pos_list.append(tmp_pos_vec[i].c_str());
  }
  ComboBoxDelegate *delegate = new ComboBoxDelegate;
  delegate->SetItemList(pos_list);
  dic_content_->setItemDelegateForColumn(2, delegate);
  if (!pos_list.isEmpty()) {
    default_pos_ = pos_list[0];
  } else {
    LOG(WARNING) << "No POS is given.";
  }

  // Set up the main table widget for dictionary contents.
  dic_content_->setColumnCount(4);
  QStringList header_labels;
  header_labels << tr("Reading") << tr("Word")
                << tr("Category") << tr("Comment");
  dic_content_->setHorizontalHeaderLabels(header_labels);

#ifdef OS_MACOSX
  // This is a workaround for MacOSX.
  // QKeysequence::Delete doesn't work on Mac,
  // so we set the key sequence directly.
  QShortcut *shortcut1 = new QShortcut(QKeySequence(Qt::Key_Backspace),
                                       dic_content_);
  // Qt::CTRL = Command key
  // Command+Backspace = delete
  QShortcut *shortcut2 = new QShortcut(QKeySequence(Qt::CTRL +
                                                    Qt::Key_Backspace),
                                       dic_content_);
  connect(shortcut1, SIGNAL(activated()), this, SLOT(DeleteWord()));
  connect(shortcut2, SIGNAL(activated()), this, SLOT(DeleteWord()));
#else
  QShortcut *shortcut = new QShortcut(QKeySequence(QKeySequence::Delete),
                                      dic_content_);
  connect(shortcut, SIGNAL(activated()), this, SLOT(DeleteWord()));
#endif

  dic_content_->setContextMenuPolicy(Qt::CustomContextMenu);
  connect(dic_content_, SIGNAL(customContextMenuRequested(const QPoint &)),
          this, SLOT(OnContextMenuRequestedForContent(const QPoint &)));
  connect(dic_content_->horizontalHeader(), SIGNAL(sectionClicked(int)),
          this, SLOT(OnHeaderClicked(int)));

  dic_list_->setContextMenuPolicy(Qt::CustomContextMenu);
  connect(dic_list_, SIGNAL(customContextMenuRequested(const QPoint &)),
          this, SLOT(OnContextMenuRequestedForList(const QPoint &)));

  // Set up the menu for dictionary related operations.
  new_action_    = dic_menu_->addAction(tr("New dictionary..."));
  rename_action_ = dic_menu_->addAction(tr("Rename dictionary..."));
  delete_action_ = dic_menu_->addAction(tr("Delete dictionary"));
  find_action_   = dic_menu_->addAction(tr("Find..."));
  dic_menu_->addSeparator();
  import_create_action_ =
      dic_menu_->addAction(tr("Import as new dictionary..."));
  import_append_action_ =
      dic_menu_->addAction(tr("Import to current dictionary..."));
  export_action_ = dic_menu_->addAction(tr("Export current dictionary..."));

  // add Import from MS-IME's dictionary
#ifdef OS_WIN
  dic_menu_->addSeparator();
  import_default_ime_action_ =
      dic_menu_->addAction(
          tr("Import from %1's user dictionary...").arg("Microsoft IME"));
#endif  // OS_WIN

  dic_menu_button_->setMenu(dic_menu_);
  connect(new_action_, SIGNAL(triggered()),
          this, SLOT(CreateDictionary()));
  connect(rename_action_, SIGNAL(triggered()),
          this, SLOT(RenameDictionary()));
  connect(delete_action_, SIGNAL(triggered()),
          this, SLOT(DeleteDictionary()));
  connect(find_action_, SIGNAL(triggered()),
          find_dialog_, SLOT(show()));
  connect(import_create_action_, SIGNAL(triggered()),
          this, SLOT(ImportAndCreateDictionary()));
  connect(import_append_action_, SIGNAL(triggered()),
          this, SLOT(ImportAndAppendDictionary()));
  connect(export_action_, SIGNAL(triggered()),
          this, SLOT(ExportDictionary()));

#ifdef OS_WIN
  connect(import_default_ime_action_, SIGNAL(triggered()),
          this, SLOT(ImportFromDefaultIME()));
#endif  // OS_WIN

  // Signals and slots to connect buttons to actions.
  connect(new_word_button_, SIGNAL(clicked()),
          this, SLOT(AddWord()));
  connect(delete_word_button_, SIGNAL(clicked()),
          this, SLOT(DeleteWord()));

  // When empty area of Dictionary Table is clicked,
  // insert a new word. This is only enabled on Mac
  connect(dic_content_, SIGNAL(emptyAreaClicked()),
          this, SLOT(AddWord()));

  // Signals and slots to update state of objects on the window in
  // response to change of selection/data of items.
  connect(dic_list_, SIGNAL(itemSelectionChanged()),
          this, SLOT(OnDictionarySelectionChanged()));

  // Initialize the list widget for a list of dictionaries.
  InitDictionaryList();
  if (dic_list_->count() != 0) {
    dic_list_->setCurrentRow(0);
  } else {
    // Make sure that the table widget is initialized when there is no
    // dictionary.
    OnDictionarySelectionChanged();
  }

  // Adjust the splitter.
  splitter_->setSizes(QList<int>()
                      << static_cast<int>(width() * 0.25)
                      << static_cast<int>(width() * 0.75));

  // adjust column width
  dic_content_->setColumnWidth(0, static_cast<int>(width() * 0.18));
  dic_content_->setColumnWidth(1, static_cast<int>(width() * 0.18));
  dic_content_->setColumnWidth(2, static_cast<int>(width() * 0.18));

  sort_state_.sorted = false;

  // If this is the first time for the user dictionary is used, create
  // a defautl dictionary.
  if (!session_->mutable_storage()->Exists()) {
    CreateDictionaryHelper(tr("User Dictionary 1"));
  }

  // for Mac-like style
#ifdef OS_MACOSX
  setUnifiedTitleAndToolBarOnMac(true);
  InstallStyleSheet(":mac_style.qss");
#endif

  // for Window Aero Glass support
#ifdef OS_WIN
  setContentsMargins(0, 0, 0, 0);
  WinUtil::InstallStyleSheetsFiles(":win_aero_style.qss",
                                   ":win_style.qss");
  if (gui::WinUtil::IsCompositionEnabled()) {
    WinUtil::ExtendFrameIntoClientArea(this);
    InstallStyleSheet(":win_aero_style.qss");
  } else {
    InstallStyleSheet(":win_style.qss");
  }
#endif

  StartMonitoringUserEdit();
  UpdateUIStatus();

  qApp->installEventFilter(this);
}

DictionaryTool::~DictionaryTool() {}

void DictionaryTool::closeEvent(QCloseEvent *event) {
  // QEvent::ApplicationDeactivate is not emitted here.

  // Change the focus so that the last incomplete itmes on
  // TableView is submitted to the model
  dic_menu_button_->setFocus(Qt::MouseFocusReason);

  SyncToStorage();
  SaveAndReloadServer();

  if (session_->mutable_storage()->GetLastError()
      == mozc::UserDictionaryStorage::TOO_BIG_FILE_BYTES) {
    QMessageBox::warning(
        this, window_title_,
        tr("Making dangerously large user dictionary file. "
           "If the dictionary file turns out to be larger than 256Mbyte, "
           "the dictionary loader skips to handle all the words to prevent "
           "the converter from being halted."));
  }
}

void DictionaryTool::OnDeactivate() {
  SyncToStorage();
  SaveAndReloadServer();
}

bool DictionaryTool::eventFilter(QObject *obj, QEvent *event) {
  // When application focus leaves, reload the server so
  // that new dictionary can be loaded.
  // This is an approximation of dynamic relading.
  //
  // We cannot call OnDeactivate() inside event filter,
  // as pending changes are not correctly synced to the disk.
  // Seems that all pending changes are committed to the UI
  // AFTER DictionaryTool receives ApplicationDeactivate event.
  // Here we delayed the execution of OnDeactivate() using QTimer.
  // This is an workaround for http://b/2190275.
  // TODO(taku): Find out a better way.
  if (event->type() == QEvent::ApplicationDeactivate) {
    const int kDelayOnDeactivateTime = 200;
    QTimer::singleShot(kDelayOnDeactivateTime, this, SLOT(OnDeactivate()));
  }
  return QWidget::eventFilter(obj, event);
}

void DictionaryTool::OnDictionarySelectionChanged() {
  SyncToStorage();

  DictionaryInfo dic_info = current_dictionary();
  if (dic_info.item == NULL) {
    current_dic_id_ = 0;
    StopMonitoringUserEdit();
    dic_content_->clearContents();
    dic_content_->setRowCount(0);
    dic_content_->setEnabled(false);
    StartMonitoringUserEdit();
    new_word_button_->setEnabled(false);
    delete_word_button_->setEnabled(false);
    rename_action_->setEnabled(false);
    delete_action_->setEnabled(false);
    import_append_action_->setEnabled(false);
    export_action_->setEnabled(false);
  } else {
    current_dic_id_ = dic_info.id;
    max_entry_size_ = mozc::UserDictionaryStorage::max_entry_size();
    SetupDicContentEditor(dic_info);
  }
}

void DictionaryTool::SetupDicContentEditor(
    const DictionaryInfo &dic_info) {
  UserDictionary *dic =
      session_->mutable_storage()->GetUserDictionary(dic_info.id);

  if (dic == NULL) {
    LOG(ERROR) << "Failed to load the dictionary: " << dic_info.id;
    ReportError();
    return;
  }

  // Update the main table widget for dictionary contents.
  StopMonitoringUserEdit();

  rename_action_->setEnabled(true);
  delete_action_->setEnabled(true);
  import_append_action_->setEnabled(true);
  export_action_->setEnabled(true);

  setUpdatesEnabled(false);

  dic_content_->clearContents();
  dic_content_->setRowCount(dic->entries_size());

  {
    scoped_ptr<QProgressDialog> progress(CreateProgressDialog(
        tr("Updating the current view data..."),
        this,
        dic->entries_size()));

    for (size_t i = 0; i < dic->entries_size(); ++i) {
      dic_content_->setItem(
          i, 0, new QTableWidgetItem(dic->entries(i).key().c_str()));
      dic_content_->setItem(
          i, 1, new QTableWidgetItem(dic->entries(i).value().c_str()));
      dic_content_->setItem(
          i, 2, new QTableWidgetItem(
              UserDictionaryUtil::GetStringPosType(dic->entries(i).pos())));
      dic_content_->setItem(
          i, 3, new QTableWidgetItem(dic->entries(i).comment().c_str()));
      progress->setValue(i);
    }
  }

  setUpdatesEnabled(true);
  dic_content_->repaint();
  dic_content_->setEnabled(true);

  StartMonitoringUserEdit();

  // Update state of other GUI components.
  UpdateUIStatus();

  const bool dictionary_is_full = dic_content_->rowCount() >= max_entry_size_;
  new_word_button_->setEnabled(!dictionary_is_full);

  modified_ = false;
}

void DictionaryTool::CreateDictionary() {
  const int max_size =
      static_cast<int>(mozc::UserDictionaryStorage::max_dictionary_size());
  if (dic_list_->count() >= max_size) {
    QMessageBox::critical(
        this, window_title_,
        tr("You can't have more than %1 dictionaries.").arg(max_size));
    return;
  }

  const QString dic_name =
      PromptForDictionaryName("", tr("Name of the new dictionary"));
  if (dic_name.isEmpty()) {
    return;  // canceld by user
  }

  SyncToStorage();

  CreateDictionaryHelper(dic_name);
}

void DictionaryTool::DeleteDictionary() {
  DictionaryInfo dic_info = current_dictionary();
  if (dic_info.item == NULL) {
    QMessageBox::information(this, window_title_,
                             tr("No dictionary is selected."));
    return;
  }

  if (QMessageBox::question(
          this, window_title_,
          tr("Do you want to delete %1?").arg(dic_info.item->text()),
          QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
      != QMessageBox::Yes) {
    return;
  }

  if (!session_->mutable_storage()->DeleteDictionary(dic_info.id)) {
    LOG(ERROR) << "Failed to delete the dictionary.";
    ReportError();
    return;
  }

  modified_ = false;
  QListWidgetItem *item = dic_list_->takeItem(dic_info.row);
  delete item;

  UpdateUIStatus();
}

void DictionaryTool::RenameDictionary() {
  DictionaryInfo dic_info = current_dictionary();
  if (dic_info.item == NULL) {
    QMessageBox::information(this, window_title_,
                             tr("No dictionary is selected."));
    return;
  }

  const QString dic_name =
      PromptForDictionaryName(dic_info.item->text(),
                              tr("New name of the dictionary"));
  if (dic_name.isEmpty()) {
    return;
  }

  if (!session_->mutable_storage()->RenameDictionary(
          dic_info.id, dic_name.toStdString())) {
    LOG(ERROR) << "Failed to rename the dictionary.";
    ReportError();
    return;
  }

  dic_info.item->setText(dic_name);

  UpdateUIStatus();
}

void DictionaryTool::ImportAndCreateDictionary() {
  const int max_size = static_cast<int>(
      mozc::UserDictionaryStorage::max_dictionary_size());
  if (dic_list_->count() >= max_size) {
    QMessageBox::critical(
        this, window_title_,
        tr("You can't have more than %1 dictionaries.").arg(max_size));
    return;
  }

  // Get necessary information from the user.
  if (import_dialog_->ExecInCreateMode() != QDialog::Accepted) {
    LOG(WARNING) << "Cancele by the user.";
    return;
  }

  ImportHelper(0,   // dic_id == 0 means that "CreateNewDictonary" mode
               import_dialog_->dic_name().toStdString(),
               import_dialog_->file_name().toStdString(),
               import_dialog_->ime_type(),
               import_dialog_->encoding_type());
}

void DictionaryTool::ImportAndAppendDictionary() {
  DictionaryInfo dic_info = current_dictionary();
  if (dic_info.item == NULL) {
    LOG(WARNING) << "No dictionary to import is selected";
    QMessageBox::information(this, window_title_,
                             tr("No dictionary is selected."));
    return;
  }

  if (dic_content_->rowCount() >= max_entry_size_) {
    QMessageBox::critical(this, window_title_,
                          tr("You can't have more than %1 "
                             "words in one dictionary.").arg(max_entry_size_));
    return;
  }

  if (import_dialog_->ExecInAppendMode() != QDialog::Accepted) {
    LOG(WARNING) << "Cancele by the user.";
    return;
  }

  ImportHelper(dic_info.id,
               dic_info.item->text().toStdString(),
               import_dialog_->file_name().toStdString(),
               import_dialog_->ime_type(),
               import_dialog_->encoding_type());
}

void DictionaryTool::ReportImportError(UserDictionaryImporter::ErrorType error,
                                       const string &dic_name,
                                       int added_entries_size) {
  switch (error) {
    case UserDictionaryImporter::IMPORT_NO_ERROR:
      QMessageBox::information(
          this, window_title_,
          tr("%1 entries are imported to %2.")
          .arg(added_entries_size).arg(dic_name.c_str()));
      break;
    case UserDictionaryImporter::IMPORT_NOT_SUPPORTED:
      QMessageBox::information(
          this, window_title_,
          tr("You have imported a file in an invalid or "
             "unsupported file format.\n\n"
             "Please check the file format. "
             "ATOK11 or older format is not supported by "
             "Mozc."));
      break;
    case UserDictionaryImporter::IMPORT_TOO_MANY_WORDS:
      QMessageBox::information(
          this, window_title_,
          tr("%1 doesn't have enough space to import all words in "
             "the file. First %2 entries "
             "are imported.").arg(dic_name.c_str()).arg(added_entries_size));
      break;
    case UserDictionaryImporter::IMPORT_INVALID_ENTRIES:
      QMessageBox::information(
          this, window_title_,
          tr("%1 entries are imported to %2.\n\nSome imported "
             "words were not recognized by %3. "
             "Please check the original import file.").
          arg(added_entries_size).arg(dic_name.c_str()).arg(window_title_));
      break;
    case UserDictionaryImporter::IMPORT_FATAL:
      QMessageBox::critical(this, window_title_,
                            tr("Failed to open user dictionary"));
      break;
    default:
      break;
  }
}

void DictionaryTool::ImportHelper(
    uint64 dic_id,
    const string &dic_name,
    const string &file_name,
    UserDictionaryImporter::IMEType ime_type,
    UserDictionaryImporter::EncodingType encoding_type) {
  if (!IsReadableToImport(file_name)) {
    LOG(ERROR) << "File is not readable to import.";
    QMessageBox::critical(this, window_title_,
                          tr("Can't open %1.").arg(file_name.c_str()));
    return;
  }

  if (dic_id == 0 &&
      !session_->mutable_storage()->CreateDictionary(dic_name, &dic_id)) {
    LOG(ERROR) << "Failed to create the dictionary.";
    ReportError();
    return;
  }

  UserDictionary *dic = session_->mutable_storage()->GetUserDictionary(dic_id);

  if (dic == NULL) {
    LOG(ERROR) << "Cannot find dictionary id: " << dic_id;
    ReportError();
    return;
  }

  if (dic->name() != dic_name) {
    LOG(ERROR) << "Dictionary name is inconsistent";
    ReportError();
    return;
  }

  // Everything looks Okey so far. Now starting import operation.
  SyncToStorage();

  // Open dictionary
  scoped_ptr<UserDictionaryImporter::TextLineIteratorInterface> iter(
      CreateTextLineIterator(encoding_type, file_name, this));
  if (iter.get() == NULL) {
    LOG(ERROR) << "CreateTextLineIterator returns NULL";
    return;
  }

  const int old_size = dic->entries_size();
  const UserDictionaryImporter::ErrorType error =
      UserDictionaryImporter::ImportFromTextLineIterator(ime_type,
                                                         iter.get(),
                                                         dic);

  const int added_entries_size = dic->entries_size() - old_size;

  // Update window state.
  InitDictionaryList();
  for (int row = 0; row < dic_list_->count(); ++row) {
    if (dic_id == dic_list_->item(row)->data(Qt::UserRole).toULongLong()) {
      dic_list_->setCurrentRow(row);
    }
  }

  UpdateUIStatus();

  ReportImportError(error, dic_name, added_entries_size);
}

void DictionaryTool::ImportFromDefaultIME() {
#ifdef OS_WIN
  if (RunLevel::IsElevatedByUAC()) {
    // MS-IME's dictionary importer doesn't work if the current
    // process is already elevated by UAC. If user disables UAC<
    // it's not the case. Here we simply remove the MS-IME import function
    // if dictionary tool is UAC-elevated
    QMessageBox::warning(this, window_title_,
                         tr("Microsoft IME dictionary import function doesn't "
                            "work on UAC-elevated process."));
    return;
  }

  DictionaryInfo dic_info = current_dictionary();
  if (dic_info.item == NULL) {
    LOG(WARNING) << "No dictionary to import is selected";
    QMessageBox::information(this, window_title_,
                             tr("No dictionary is selected."));
    return;
  }

  const QMessageBox::StandardButton answer =
      QMessageBox::information(this, window_title_,
                               tr("All user-registered words in %1 "
                                  "are migrated into the "
                                  "current dictionary.").arg("Microsoft IME"),
                               QMessageBox::Ok | QMessageBox::Cancel,
                               QMessageBox::Cancel);
  if (answer != QMessageBox::Ok) {
    LOG(WARNING) << "Cancele by the user.";
    return;
  }

  SyncToStorage();

  UserDictionary *dic =
      session_->mutable_storage()->GetUserDictionary(dic_info.id);
  DCHECK(dic);

  const int old_size = dic->entries_size();
  const string dic_name = dic_info.item->text().toStdString();

  const UserDictionaryImporter::ErrorType error =
      UserDictionaryImporter::ImportFromMSIME(dic);

  const int added_entries_size = dic->entries_size() - old_size;

  OnDictionarySelectionChanged();
  UpdateUIStatus();

  ReportImportError(error, dic_name, added_entries_size);
#endif
}

void DictionaryTool::ExportDictionary() {
  DictionaryInfo dic_info = current_dictionary();
  if (dic_info.item == NULL) {
    LOG(WARNING) << "No dictionary to export is selected";
    QMessageBox::information(this, window_title_,
                             tr("No dictionary is selected."));
    return;
  }

  const string file_name = QFileDialog::getSaveFileName(
      this, tr("Export dictionary"),
      QDir::homePath(), tr("Text Files (*.txt);;All Files (*)")).toStdString();
  if (file_name.empty()) {
    return;
  }

  if (!IsWritableToExport(file_name)) {
    LOG(ERROR) << "File is not writable to export.";
    QMessageBox::critical(this, window_title_,
                          tr("Can't open %1.").arg(file_name.c_str()));
    return;
  }

  SyncToStorage();

  if (!session_->mutable_storage()->ExportDictionary(dic_info.id, file_name)) {
    LOG(ERROR) << "Failed to export the dictionary.";
    ReportError();
    return;
  }

  QMessageBox::information(this, window_title_,
                           tr("Dictionary export finished."));
}

void DictionaryTool::AddWord() {
  const int row = dic_content_->rowCount();
  if (row >= max_entry_size_) {
    QMessageBox::information(
        this, window_title_,
        tr("You can't have more than %1 words in one dictionary.").arg(
            max_entry_size_));
    return;
  }

  dic_content_->insertRow(row);
  dic_content_->setItem(row, 0, new QTableWidgetItem(""));
  dic_content_->setItem(row, 1, new QTableWidgetItem(""));
  dic_content_->setItem(row, 2, new QTableWidgetItem(default_pos_));
  dic_content_->setItem(row, 3, new QTableWidgetItem(""));

  if (row + 1 >= max_entry_size_) {
    new_word_button_->setEnabled(false);
  }

  QTableWidgetItem *item = dic_content_->item(row, 0);
  dic_content_->setCurrentItem(item);
  dic_content_->editItem(item);

  UpdateUIStatus();
}

void DictionaryTool::GetSortedSelectedRows(vector<int> *rows) const {
  DCHECK(rows);
  rows->clear();

  const QList<QTableWidgetItem *> items = dic_content_->selectedItems();
  if (items.empty()) {
    return;
  }
  rows->reserve(items.count());
  for (int i = 0; i < items.size(); ++i) {
    rows->push_back(items[i]->row());
  }

  sort(rows->begin(), rows->end(), greater<int>());
  vector<int>::const_iterator end = unique(rows->begin(), rows->end());

  rows->resize(end - rows->begin());
}

QListWidgetItem *DictionaryTool::GetFirstSelectedDictionary() const {
  QList<QListWidgetItem *> selected_dicts = dic_list_->selectedItems();
  if (selected_dicts.isEmpty()) {
    LOG(WARNING) << "No current dictionary.";
    return NULL;
  }
  if (selected_dicts.size() > 1) {
    LOG(WARNING) << "Multiple items are selected.";
  }
  return selected_dicts[0];
}

void DictionaryTool::DeleteWord() {
  vector<int> rows;
  GetSortedSelectedRows(&rows);
  if (rows.size() == 0) {
    return;
  }

  QString message;
  if (rows.size() == 1) {
    message = tr("Do you want to delete this word?");
  } else {
    message = tr("Do you want to delete the selected words?");
  }
  if (QMessageBox::question(
          this, window_title_, message,
          QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
      != QMessageBox::Yes) {
    return;
  }

  setUpdatesEnabled(false);

  {
    scoped_ptr<QProgressDialog> progress(
        CreateProgressDialog(
            tr("Deleting the selected words..."),
            this,
            rows.size()));

    for (size_t i = 0; i < rows.size(); ++i) {
      dic_content_->removeRow(rows[i]);
      progress->setValue(i);
    }
  }

  setUpdatesEnabled(true);
  dic_content_->setEnabled(true);

  if (dic_content_->rowCount() < max_entry_size_) {
    new_word_button_->setEnabled(true);
  }

  UpdateUIStatus();
  dic_content_->repaint();

  modified_ = true;
}

void DictionaryTool::EditPOS(const string &pos) {
  const QList<QTableWidgetItem *> items =
      dic_content_->selectedItems();
  if (items.empty()) {
    return;
  }

  const QString new_pos = QString::fromUtf8(pos.c_str());
  setUpdatesEnabled(false);

  for (int i = 0; i < items.size(); ++i) {
    const int row = items[i]->row();
    dic_content_->setItem(row, 2, new QTableWidgetItem(new_pos));
  }

  setUpdatesEnabled(true);
  dic_content_->setEnabled(true);
}

void DictionaryTool::MoveTo(int dictionary_row) {
  UserDictionary *target_dict = NULL;
  {
    const QListWidgetItem * selected_dict = GetFirstSelectedDictionary();
    if (selected_dict == NULL) {
      return;
    }
    QListWidgetItem *target_dict_item = dic_list_->item(dictionary_row);
    DCHECK(target_dict_item);
    if (target_dict_item == selected_dict) {
      LOG(WARNING) << "Target dictionary is the current dictionary.";
      return;
    }

    target_dict = session_->mutable_storage()->GetUserDictionary(
        target_dict_item->data(Qt::UserRole).toULongLong());
  }

  vector<int> rows;
  GetSortedSelectedRows(&rows);
  if (rows.size() == 0) {
    return;
  }

  const size_t target_max_entry_size =
      mozc::UserDictionaryStorage::max_entry_size();

  if (target_dict->entries_size() + rows.size() > target_max_entry_size) {
    QMessageBox::critical(this, window_title_,
                          tr("Cannot move all the selected items.\n"
                             "The target dictionary can have maximum "
                             "%1 entries.").arg(target_max_entry_size));
    return;
  }

  setUpdatesEnabled(false);

  {
    // add |rows.size()| items and remove |rows.size()| items
    const int progress_max = rows.size() * 2;
    scoped_ptr<QProgressDialog> progress(
        CreateProgressDialog(
            tr("Moving the selected words..."),
            this,
            progress_max));

    int progress_index = 0;
    if (target_dict) {
      for (size_t i = 0; i < rows.size(); ++i) {
        UserDictionary::Entry *entry = target_dict->add_entries();
        const int row = rows[i];
        entry->set_key(dic_content_->item(row, 0)->text().toStdString());
        entry->set_value(dic_content_->item(row, 1)->text().toStdString());
        entry->set_pos(UserDictionaryUtil::ToPosType(
            dic_content_->item(row, 2)->text().toStdString().c_str()));
        entry->set_comment(dic_content_->item(row, 3)->text().toStdString());
        UserDictionaryUtil::SanitizeEntry(entry);
        progress->setValue(progress_index);
        ++progress_index;
      }
    }
    for (size_t i = 0; i < rows.size(); ++i) {
      dic_content_->removeRow(rows[i]);
      progress->setValue(progress_index);
      ++progress_index;
    }
  }

  setUpdatesEnabled(true);
  dic_content_->setEnabled(true);

  UpdateUIStatus();
  dic_content_->repaint();

  modified_ = true;
}

void DictionaryTool::EditComment() {
  const QList<QTableWidgetItem *> items =
      dic_content_->selectedItems();
  if (items.empty()) {
    return;
  }

  bool ok = false;
  const QString new_comment = QInputDialog::getText(
      this, window_title_, tr("New comment"),
      QLineEdit::Normal, "", &ok,
      Qt::WindowTitleHint | Qt::WindowSystemMenuHint);

  if (!ok) {
    return;
  }

  setUpdatesEnabled(false);
  for (int i = 0; i < items.size(); ++i) {
    const int row = items[i]->row();
    dic_content_->setItem(row, 3, new QTableWidgetItem(new_comment));
  }

  setUpdatesEnabled(true);
  dic_content_->setEnabled(true);
}

void DictionaryTool::CloseWindow() {
  // move the focus to the close button to submit all incomplete inputs in
  // the word cells. http://b/211766
  // This is reuqired for MacOSX
  new_word_button_->setFocus();
  this->close();
}

void DictionaryTool::OnItemChanged(QTableWidgetItem *item) {
  if (item->column() == 0 &&
      !item->text().isEmpty() &&
      !UserDictionaryUtil::IsValidReading(item->text().toStdString())) {
    QMessageBox::critical(
        this, window_title_,
        tr("An invalid character is included in the reading."));
  }

  UpdateUIStatus();

  sort_state_.sorted = false;
  modified_ = true;
}

void DictionaryTool::OnHeaderClicked(int logicalIndex) {
  if (sort_state_.sorted &&
      sort_state_.column == logicalIndex &&
      sort_state_.order == Qt::AscendingOrder) {
    dic_content_->sortItems(logicalIndex, Qt::DescendingOrder);
    sort_state_.order = Qt::DescendingOrder;
  } else {
    dic_content_->sortItems(logicalIndex, Qt::AscendingOrder);
    sort_state_.sorted = true;
    sort_state_.column = logicalIndex;
    sort_state_.order = Qt::AscendingOrder;
  }
  modified_ = true;
}

void DictionaryTool::OnContextMenuRequestedForContent(const QPoint &pos) {
  QTableWidgetItem *item = dic_content_->itemAt(pos);
  // When the mouse pointer is not on an item of the table widget, we
  // don't show context menu.
  if (item == NULL) {
    return;
  }

  QMenu *menu = new QMenu(this);
  QAction *add_action = menu->addAction(tr("Add a word"));

  // Count the number of selected words and create delete menu with an
  // appropriate text.
  const QList<QTableWidgetItem *> items = dic_content_->selectedItems();
  QString delete_menu_text = tr("Delete this word");
  QString move_to_menu_text = tr("Move this word to");
  if (items.size() > 0) {
    const int first_row = items[0]->row();
    for (int i = 1; i < items.size(); ++i) {
      if (items[i]->row() != first_row) {
        // More than one words are selected.
        delete_menu_text = tr("Delete the selected words");
        move_to_menu_text = tr("Move the selected words to");
        break;
      }
    }
  }
  vector<pair<int, QAction *> > change_dictionary_actions;
  // "Move to" is available only when we have 2 or more dictionaries.
  if (dic_list_->count() > 1) {
    QMenu *move_to = menu->addMenu(move_to_menu_text);
    change_dictionary_actions.reserve(dic_list_->count() - 1);
    {
      const QListWidgetItem *selected_dict = GetFirstSelectedDictionary();
      if (selected_dict != NULL) {
        for (size_t i = 0; i < dic_list_->count(); ++i) {
          QListWidgetItem *item = dic_list_->item(i);
          DCHECK(item);
          if (item == selected_dict) {
            // Do not add the current dictionary into the "Move to" list.
            continue;
          }
          change_dictionary_actions.push_back(
              make_pair(i, move_to->addAction(item->text())));
        }
      }
    }
  }
  QAction *delete_action = menu->addAction(delete_menu_text);

  menu->addSeparator();
  QMenu *change_category_to = menu->addMenu(tr("Change category to"));
  vector<string> pos_list;
  user_pos_->GetPOSList(&pos_list);
  vector<QAction *> change_pos_actions(pos_list.size());
  for (size_t i = 0; i < pos_list.size(); ++i) {
    change_pos_actions[i] = change_category_to->addAction(
        QString::fromUtf8(pos_list[i].c_str()));
  }
  QAction *edit_comment_action = menu->addAction(tr("Edit comment"));

  QAction *selected_action = menu->exec(QCursor::pos());

  if (selected_action == add_action) {
    AddWord();
  } else if (selected_action == delete_action) {
    DeleteWord();
  } else if (selected_action == edit_comment_action) {
    EditComment();
  } else {
    bool found = false;
    for (int i = 0; i < change_pos_actions.size(); ++i) {
      if (selected_action == change_pos_actions[i]) {
        EditPOS(pos_list[i]);
        found = true;
        break;
      }
    }
    if (!found) {
      for (int i = 0; i < change_dictionary_actions.size(); ++i) {
        if (selected_action == change_dictionary_actions[i].second) {
          MoveTo(change_dictionary_actions[i].first);
          found = true;
          break;
        }
      }
    }
  }
}

void DictionaryTool::OnContextMenuRequestedForList(const QPoint &pos) {
  QListWidgetItem *item = dic_list_->itemAt(pos);
  if (item == NULL) {
    return;
  }

  QMenu *menu = new QMenu(this);

  QAction *rename_action = menu->addAction(tr("Rename..."));
  QAction *delete_action = menu->addAction(tr("Delete"));
  QAction *import_action = menu->addAction(tr("Import to this dictionary..."));
  QAction *export_action = menu->addAction(tr("Export this dictionary..."));
  QAction *selected_action = menu->exec(QCursor::pos());

  if ((rename_action != NULL) && (selected_action == rename_action)) {
    RenameDictionary();
  } else if ((delete_action != NULL) && (selected_action == delete_action)) {
    DeleteDictionary();
  } else if ((import_action != NULL) && (selected_action == import_action)) {
    ImportAndAppendDictionary();
  } else if ((export_action != NULL) && (selected_action == export_action)) {
    ExportDictionary();
  }
}

DictionaryTool::DictionaryInfo DictionaryTool::current_dictionary() const {
  DictionaryInfo retval = { -1, 0, NULL };

  QListWidgetItem *selected_dict = GetFirstSelectedDictionary();
  if (selected_dict == NULL) {
    return retval;
  }

  retval.row  = dic_list_->row(selected_dict);
  retval.id   = selected_dict->data(Qt::UserRole).toULongLong();
  retval.item = selected_dict;
  return retval;
}

void DictionaryTool::SyncToStorage() {
  if (current_dic_id_ == 0 || !modified_) {
    return;
  }

  UserDictionary *dic =
      session_->mutable_storage()->GetUserDictionary(current_dic_id_);

  if (dic == NULL) {
    LOG(ERROR) << "No save dictionary: " << current_dic_id_;
    return;
  }

  dic->clear_entries();

  for (int i = 0; i < dic_content_->rowCount(); ++i) {
    UserDictionary::Entry *entry =
        dic->add_entries();
    entry->set_key(dic_content_->item(i, 0)->text().toStdString());
    entry->set_value(dic_content_->item(i, 1)->text().toStdString());
    entry->set_pos(UserDictionaryUtil::ToPosType(
        dic_content_->item(i, 2)->text().toStdString().c_str()));
    entry->set_comment(dic_content_->item(i, 3)->text().toStdString());
    UserDictionaryUtil::SanitizeEntry(entry);
  }

  modified_ = false;
}

void DictionaryTool::CreateDictionaryHelper(const QString &dic_name) {
  uint64 new_dic_id = 0;
  if (!session_->mutable_storage()->CreateDictionary(
          dic_name.toStdString(),
          &new_dic_id)) {
    LOG(ERROR) << "Failed to create a new dictionary.";
    ReportError();
    return;
  }

  QListWidgetItem *item = new QListWidgetItem(dic_list_);
  DCHECK(item);
  item->setText(dic_name);
  item->setData(Qt::UserRole,
                QVariant(static_cast<qulonglong>(new_dic_id)));

  dic_list_->setCurrentRow(dic_list_->row(item));

  AddWord();
}

bool DictionaryTool::InitDictionaryList() {
  dic_list_->clear();
  const UserDictionaryStorage &storage = session_->storage();

  for (size_t i = 0; i < storage.dictionaries_size(); ++i) {
    QListWidgetItem *item = new QListWidgetItem(dic_list_);
    DCHECK(item);
    item->setText(storage.dictionaries(i).name().c_str());
    item->setData(Qt::UserRole,
                  QVariant(
                      static_cast<qulonglong>(storage.dictionaries(i).id())));
  }

  UpdateUIStatus();

  return true;
}

QString DictionaryTool::PromptForDictionaryName(const QString &text,
                                                const QString &label) {
  bool ok = false;
  QString dic_name;
  do {
    dic_name = QInputDialog::getText(
        this, window_title_, label, QLineEdit::Normal, text, &ok,
        // To disable context help on Windows.
        Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
  } while (ok && dic_name.isEmpty());

  if (!ok) {
    LOG(WARNING) << "Canceled by the user.";
    return "";
  }

  return dic_name;
}

void DictionaryTool::ReportError() {
  switch (session_->mutable_storage()->GetLastError()) {
    case mozc::UserDictionaryStorage::INVALID_CHARACTERS_IN_DICTIONARY_NAME:
      LOG(ERROR) << "Dictionary name contains an invalid character.";
      QMessageBox::critical(
          this, window_title_,
          tr("An invalid character is included in the dictionary name."));
      break;
    case mozc::UserDictionaryStorage::EMPTY_DICTIONARY_NAME:
      LOG(ERROR) << "Dictionary name is empty.";
      QMessageBox::critical(this, window_title_,
                            tr("Dictionary name is empty."));
      break;
    case mozc::UserDictionaryStorage::TOO_LONG_DICTIONARY_NAME:
      LOG(ERROR) << "Dictionary name is too long.";
      QMessageBox::critical(this, window_title_,
                            tr("Dictionary name is too long."));
      break;
    case mozc::UserDictionaryStorage::DUPLICATED_DICTIONARY_NAME:
      LOG(ERROR) << "duplicated dictionary name";
      QMessageBox::critical(this, window_title_,
                            tr("Dictionary already exists."));
      break;
    default:
      LOG(ERROR) << "A fatal error occurred";
      QMessageBox::critical(this, window_title_,
                            tr("A fatal error occurred."));
      break;
  }
}

void DictionaryTool::StartMonitoringUserEdit() {
  if (monitoring_user_edit_) {
    return;
  }
  connect(dic_content_, SIGNAL(itemChanged(QTableWidgetItem *)),
          this, SLOT(OnItemChanged(QTableWidgetItem *)));
  monitoring_user_edit_ = true;
}

void DictionaryTool::StopMonitoringUserEdit() {
  if (!monitoring_user_edit_) {
    return;
  }
  disconnect(dic_content_, SIGNAL(itemChanged(QTableWidgetItem *)),
             this, SLOT(OnItemChanged(QTableWidgetItem *)));
  monitoring_user_edit_ = false;
}

void DictionaryTool::SaveAndReloadServer() {
  if (!session_->mutable_storage()->Save() &&
      session_->mutable_storage()->GetLastError() ==
      mozc::UserDictionaryStorage::SYNC_FAILURE) {
    LOG(ERROR) << "Cannot save dictionary";
    return;
  }

  // If server is not running, we don't need to
  // execute Reload command.
  if (!client_->PingServer()) {
    LOG(WARNING) << "Server is not running. Do nothing";
    return;
  }

  // Update server version if need be.
  if (!client_->CheckVersionOrRestartServer()) {
    LOG(ERROR) << "CheckVersionOrRestartServer failed";
    return;
  }

  // We don't show any dialog even when an error happens, since
  // dictionary serialization is finished correctly.
  if (!client_->Reload()) {
    LOG(ERROR) << "Reload command failed";
  }
}

bool DictionaryTool::IsReadableToImport(const string &file_name) {
  QFileInfo file_info(file_name.c_str());
  return file_info.isFile() && file_info.isReadable();
}

bool DictionaryTool::IsWritableToExport(const string &file_name) {
  QFileInfo file_info(file_name.c_str());
  if (file_info.exists()) {
    return file_info.isFile() && file_info.isWritable();
  } else {
    QFileInfo dir_info(file_info.dir().absolutePath());
    // This preprocessor conditional is a workaround for a problem
    // that export fails on Windows.
#ifdef OS_WIN
    return dir_info.isExecutable();
#else
    return dir_info.isExecutable() && dir_info.isWritable();
#endif
  }
}

void DictionaryTool::paintEvent(QPaintEvent *event) {
#ifdef OS_WIN
  if (!gui::WinUtil::IsCompositionEnabled()) {
    return;
  }

  const QRect message_rect = WinUtil::GetTextRect(this, statusbar_message_);
  const int kMargin = 2;
  const int kGlowSize = 10;
  const QRect rect(QPoint(kMargin,
                          this->height() - statusbar_->height()),
                   QPoint(message_rect.width() + kMargin + kGlowSize * 2,
                          this->height()));

  statusbar_->clearMessage();
  QPainter painter(this);
  WinUtil::DrawThemeText(statusbar_message_, rect, kGlowSize, &painter);
#endif
}

void DictionaryTool::UpdateUIStatus() {
  const bool is_enable_new_dic =
      dic_list_->count() < session_->mutable_storage()->max_dictionary_size();
  new_action_->setEnabled(is_enable_new_dic);
  import_create_action_->setEnabled(is_enable_new_dic);

  delete_action_->setEnabled(dic_list_->count() > 0);
  import_append_action_->setEnabled(dic_list_->count() > 0);
#ifdef OS_WIN
  import_default_ime_action_->setEnabled(dic_list_->count() > 0);
#endif

  const bool is_enable_new_word =
      dic_list_->count() > 0 &&
      dic_content_->rowCount() < max_entry_size_;

  new_word_button_->setEnabled(is_enable_new_word);
  delete_word_button_->setEnabled(dic_content_->rowCount() > 0);

  const DictionaryInfo dic_info = current_dictionary();
  if (dic_info.item != NULL) {
    statusbar_message_ =  QString(tr("%1: %2 entries")).arg(
        dic_info.item->text()).arg(
            dic_content_->rowCount());
  } else {
    statusbar_message_.clear();
  }

#ifdef OS_WIN
  if (!gui::WinUtil::IsCompositionEnabled()) {
    statusbar_->showMessage(statusbar_message_);
  } else {
    update();
  }
#else
  statusbar_->showMessage(statusbar_message_);
#endif
}

#ifdef OS_WIN
bool DictionaryTool::winEvent(MSG *message, long *result) {
  if (message != NULL &&
      message->message == WM_LBUTTONDOWN &&
      toolbar_->cursor().shape() == Qt::ArrowCursor &&
      WinUtil::IsCompositionEnabled()) {
    const QWidget *widget = qApp->widgetAt(
        mapToGlobal(QPoint(message->lParam & 0xFFFF,
                           (message->lParam >> 16) & 0xFFFF)));
    if (widget == statusbar_ || widget == toolbar_) {
      ::PostMessage(message->hwnd, WM_NCLBUTTONDOWN,
                    static_cast<WPARAM>(HTCAPTION), message->lParam);
      return true;
    }
  }

  return QWidget::winEvent(message, result);
}
#endif
}  // namespace gui
}  // namespace mozc
