/*! @file

    @id $Id$
*/
//       1         2         3         4         5         6         7         8
// 45678901234567890123456789012345678901234567890123456789012345678901234567890

#include <qbrowserlib/log.hxx>

namespace qbrowserlib {

  bool Log::DEBUG(false);
  LogDialog* Log::_dialog(0);
  unsigned int Log::_level(0);

  Log::Log(const void* addr, const std::string& name,
           const std::string& file, unsigned long line,
           bool traceOpenClose):
      _debug(DEBUG), _close(traceOpenClose),
      _addr(addr), _name(name), _file(file), _line(line), _clean(true) {
    if (!_debug) return;
    if (_close) {
      ++_level;
      indent(_ss)<<"\\ "<<_name;
      close(init(std::clog)<<_ss.str())<<std::endl;
      if (!_dialog) _dialog = new LogDialog;
      _dialog->append(*this, _ss.str());
      _ss.str(std::string());
    }
    indent(_ss)<<"    → ";
  }
  
  Log::~Log() throw() {
    if (!_debug) return;
    if (!_clean) {
      close(init(std::clog)<<_ss.str())<<std::endl;
      if (!_dialog) _dialog = new LogDialog;
      _dialog->append(*this, _ss.str());
    }
    if (!_close) return;
    _ss.str(std::string());
    indent(_ss)<<"/ "<<_name;
    close(init(std::clog)<<_ss.str())<<std::endl;
    --_level;
    _dialog->append(*this, _ss.str());
  }
  
  void Log::show(QWidget* p) {
    if (!_dialog)
      _dialog = new LogDialog(p);
    _dialog->_logs->resizeColumnsToContents();
    _dialog->_logs->resizeRowsToContents();
    _dialog->show();
  }
  
  std::ostream& Log::init(std::ostream& ss) {
    if (_addr)
      ss<<std::hex<<std::setw(15)<<_addr<<": "<<std::dec;
    else
      ss<<std::setw(17)<<' ';
    return ss;
  }
  
  std::ostream& Log::indent(std::ostream& ss) {
    ss<<std::setw(2+_level)<<std::setfill(' ');
    return ss;
  }
  
  std::ostream& Log::close(std::ostream& ss) {
    ss<<" ("<<_file<<':'<<_line<<')';
    return ss;
  }
  
  template<> LogDialog& LogDialog::append
      (const Log& log, std::string arg) {
    return append(log, QString::fromStdString(arg));
  }
  template<> LogDialog& LogDialog::append
      (const Log& log, const char* arg) {
    return append(log, QString(arg));
  }
  template<> LogDialog& LogDialog::append
      (const Log& log, unsigned long arg) {
    return append(log, (qulonglong)arg);
  }

  std::ostream& operator<<(std::ostream& ss, QString arg) {
    ss<<'"'<<arg.toStdString()<<'"';
    return ss;
  }
  
  std::ostream& operator<<(std::ostream& ss, QStringList arg) {
    ss<<"{ ";
    for (QStringList::iterator item(arg.begin()); item!=arg.end();) {
      ss<<*item;
      if (++item!=arg.end()) ss<<", ";
    }
    ss<<" }";
    return ss;
  }
  
  std::ostream& operator<<(std::ostream& ss, QUrl arg) {
    ss<<arg.toString();
    return ss;
  }

  std::ostream& operator<<(std::ostream& ss, QByteArray arg) {
    ss<<QString::fromUtf8(arg);
    return ss;
  }

}
