/* 
 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; version 2 of the
 * License.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#include "stdafx.h"

#include "wb_context.h"
#include "output_view.h"
#include "base/string_utilities.h"

using namespace wb;

OutputView::OutputView(WBContext* context)
  : mforms::AppView(true, "output", true), _splitter(true), _message_list(mforms::TreeDefault),
  _output_text(mforms::BothScrollBars)
{
  _wb = context;
  _can_track_changes = false; // True when the UI setup is done and we can track further UI changes.

  add(&_splitter, true, true);

  _splitter.add(&_message_list);
  _splitter.add(&_output_text);
  Box::scoped_connect(_splitter.signal_position_changed(), boost::bind(&OutputView::splitter_moved, this));
  
  _message_list.add_column(mforms::IconStringGRTColumnType, 0, "");
  _message_list.set_column_width(0, 100);
  _message_list.add_column(mforms::StringGRTColumnType, 1, "Message");
  _message_list.set_column_width(1, 500);
  
  _storage = _wb->get_grt_manager()->get_messages_list();
  _storage->set_output_handler(boost::bind(&mforms::TextBox::append_text, &_output_text, _1, true));
  
  _messages = _storage->create_list();
  _message_list.set_model(_messages);
  _message_list.set_allow_multi_selection(true);
  
  UIForm::scoped_connect(_messages->signal_row_added(),boost::bind(&OutputView::row_added, this));
  
  _output_text.set_read_only(true);
  
  set_on_close(boost::bind(&OutputView::will_close, this));

  _context_menu.add_item(_("Copy selected entries to clipboard"), "copy");
  _context_menu.add_item(_("Clear output"), "clear");
  _message_list.set_context_menu(&_context_menu);
  _context_menu.set_handler(boost::bind(&OutputView::handle_command, this, _1));
}

//--------------------------------------------------------------------------------------------------

OutputView::~OutputView()
{
  _storage->set_output_handler(boost::function<void (std::string)>());
  _message_list.set_model(0);
  delete _messages;
  _messages = 0;
}

//--------------------------------------------------------------------------------------------------

void OutputView::handle_command(const std::string& command)
{
  if (command == "copy")
  {
    std::vector<bec::NodeId> selection;
    _message_list.get_selection(selection);
    std::string result;
    for (std::vector<bec::NodeId>::const_iterator iterator = selection.begin(); iterator != selection.end(); 
      iterator++)
    {
      std::string type_string;
      grt::MessageType type = _messages->get_message_type(*iterator);
      switch (type)
      {
        case grt::WarningMsg:
          type_string = _("Warning");
          break;
        case grt::ErrorMsg:
          type_string = _("Error");
          break;
        default:
          type_string = _("Info");
      }
      std::string time;
      std::string message;
      std::string details;
      _messages->get_field(*iterator, bec::MessageListBE::Time, time);
      _messages->get_field(*iterator, bec::MessageListBE::Message, message);
      if (message.empty())
        message = _("none");
      _messages->get_field(*iterator, bec::MessageListBE::Detail, details);
      if (details.empty())
        details = _("n/a");
      result.append(base::strfmt(_("%s:\tTime: %s\tMessage: %s\tDetails: %s\n"),
        type_string.c_str(), time.c_str(), message.c_str(), details.c_str()));
    }
    mforms::Utilities::set_clipboard_text(result);
  }
  else
    if (command == "clear")
    {
      _messages->clear();
      // TODO: the model should send a notification about the clearance, so that the viewer
      //       can implicitly update itself.
      _message_list.refresh(bec::NodeId());
    }
}

//--------------------------------------------------------------------------------------------------

void OutputView::row_added()
{
  _message_list.row_count_changed(bec::NodeId(), _messages->count()-1);
  _message_list.refresh(bec::NodeId()); // TODO: Must be support for row_inserted!
}

//--------------------------------------------------------------------------------------------------

bool OutputView::will_close()
{
  _can_track_changes = false;
  return true;
}

//--------------------------------------------------------------------------------------------------

void OutputView::setup_ui()
{
  int splitter_position = _wb->read_state("message_width", "output_view", 500);
  _splitter.set_position(splitter_position);
  _can_track_changes = true;
}

//--------------------------------------------------------------------------------------------------

void OutputView::splitter_moved()
{
  if (!_can_track_changes)
    return;

  int splitter_position = _splitter.get_position();
  _wb->save_state("message_width", "output_view", splitter_position);
}

//--------------------------------------------------------------------------------------------------

