/*!
  \file
  \brief 書き込み用ウィジット

  \author Satofumi KAMIMURA

  $Id: WriterWidget.cpp 1553 2009-11-29 15:47:05Z satofumi $

  \todo Ubuntu 環境で日本語のエラーメッセージ表示の動作確認行う
*/

#include "WriterWidget.h"
#include "SerialConnectionWidget.h"
#include "SformatHandler.h"
#include "FindComPorts.h"
#include "SerialDevice.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QTextCodec>
#include <QShortcut>
#include <vector>

using namespace qrk;
using namespace std;

enum {
  Baudrate = 115200,
};


struct WriterWidget::pImpl
{
  WriterWidget* widget_;
  SerialConnectionWidget connection_widget_;
  FindComPorts serial_finder_;
  SerialDevice serial_;


  pImpl(WriterWidget* widget) : widget_(widget)
  {
  }


  void initializeForm(void)
  {
    widget_->connection_dummy_label_->hide();
    widget_->connection_layout_->addWidget(&connection_widget_);
    connection_widget_.setFocus();

    connect(&connection_widget_, SIGNAL(rescanRequest()),
            widget_, SLOT(rescanPressed()));
    connect(&connection_widget_,
            SIGNAL(connectRequest(bool, const std::string&)),
            widget_, SLOT(connectPressed(bool, const std::string&)));

    connect(widget_->lineedit_, SIGNAL(textChanged(const QString&)),
            widget_, SLOT(fileUpdated(const QString&)));
    connect(widget_->path_button_, SIGNAL(clicked()),
            widget_, SLOT(pathPressed()));

    connect(widget_->write_button_, SIGNAL(clicked()),
            widget_, SLOT(writePressed()));
    connect(widget_->close_button_, SIGNAL(clicked()), widget_, SLOT(close()));
  }


  void checkWritable(void)
  {
    bool writable = true;
    if (! serial_.isConnected()) {
      // シリアル・デバイスが接続されていない
      writable = false;
    } if (widget_->lineedit_->text().isEmpty()) {
      // ファイルが指定されていない
      writable = false;
    }

    setWriteEnabled(writable);
  }


  void setWriteEnabled(bool writable)
  {
    widget_->write_button_->setEnabled(writable);
  }


  void registerFile(const QString& file)
  {
    widget_->lineedit_->setText(file);
  }
};


WriterWidget::WriterWidget(QWidget* parent)
  : QWidget(parent), pimpl(new pImpl(this))
{
  setupUi(this);
  pimpl->initializeForm();
  rescanPressed();

  (void) new QShortcut(Qt::CTRL + Qt::Key_W, this, SLOT(close()));
  (void) new QShortcut(Qt::CTRL + Qt::Key_Q, this, SLOT(close()));
  (void) new QShortcut(Qt::ALT + Qt::Key_F4, this, SLOT(close()));
}


WriterWidget::~WriterWidget(void)
{
}


void WriterWidget::rescanPressed(void)
{
  vector<string> devices;
  pimpl->serial_finder_.find(devices);
  pimpl->connection_widget_.setDevices(devices);
}


void WriterWidget::connectPressed(bool connection, const std::string& device)
{
  (void)connection;
  (void)device;

  bool connected = connection;
  if (connection) {
    connected = pimpl->serial_.connect(device.c_str(), Baudrate);
  } else {
    pimpl->serial_.disconnect();
  }

  pimpl->checkWritable();
  pimpl->connection_widget_.setConnected(connected);
}


void WriterWidget::fileUpdated(const QString& text)
{
  static_cast<void>(text);

  pimpl->checkWritable();
}


void WriterWidget::pathPressed(void)
{
  // !!! 選択されているファイルのディレクトリを開くようにする
  QString file_name =
    QFileDialog::getOpenFileName(this, tr("mot file"),
                                 "", tr("mot (*.mot)"));
  if (file_name.isEmpty()) {
    return;
  }

  // ファイルの登録
  pimpl->registerFile(file_name);
}


void WriterWidget::writePressed(void)
{
  // mot ファイルのチェック
  const char* file = lineedit_->text().toStdString().c_str();
  SformatHandler mot_file(file);
  if (mot_file.invalid()) {
    QString mot_error = mot_file.what();
#ifdef Q_WS_X11
    QTextCodec* codec = QTextCodec::codecForName("EUC-JP");
    if (codec) {
      mot_error = codec->toUnicode(mot_file.what());
    }
#endif

    QMessageBox::warning(this, tr("mot-file error"), mot_error);
    return;
  }

#if 0
  // !!! 書き込み処理を別スレッドで起動し、プログレス表示を行う

  // mot ファイルの転送と実行
  SformatSender sformat(&serial);
  if ((! sformat.send(args.file())) || (! sformat.jump(args.file()))) {
    QMessageBox::warning(this, tr("transfer error"), sformat.what());
    return;
  }

  // 結果表示
  // !!!
#endif
}
