/***************************************************************************
 *   Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org>                  *
 *                                                                         *
 *   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; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/
#ifndef LOG_H
#define LOG_H

#include <tqstringlist.h>

#include "common/common/key_enum.h"

namespace Log
{
  // immediat visibily by calling processEvent... BEWARE of side effects
  enum Action { Immediate, Delayed };
  enum ShowMode { DontShow, Show };
  struct LogData {
    const char *key, *label, *color;
    bool bold;
  };
  BEGIN_DECLARE_ENUM(DebugLevel)
    Quiet = 0, Normal, Extra, Max, LowLevel
  END_DECLARE_ENUM(DebugLevel, LogData)
  BEGIN_DECLARE_ENUM(LineType)
    Error = 0, SoftError, Warning, Normal, Information, Command
  END_DECLARE_ENUM(LineType, LogData)

//-----------------------------------------------------------------------------
class Generic
{
public:
  virtual ~Generic() {}
  virtual void log(LineType type, const TQString &text, Action action = Immediate) = 0;
  virtual void log(DebugLevel level, const TQString &text, Action action = Immediate) = 0;
  virtual void appendToLastLine(const TQString &text) = 0;
  virtual void sorry(const TQString &message, const TQString &details) = 0;
  virtual bool askContinue(const TQString &message) = 0;
  virtual void clear() = 0;
  virtual void logUserAbort() = 0;
};

class View : public Generic
{
public:
  View();
  ShowMode showMode(LineType type) const { return _modes[type.type()]; }
  void setShowMode(LineType type, ShowMode mode) { _modes[type.type()] = mode; }
  void setDebugLevel(DebugLevel level);
  virtual void log(LineType type, const TQString &text, Action action = Immediate);
  virtual void log(DebugLevel level, const TQString &text, Action action = Immediate);
  virtual void logUserAbort();

protected:
  ShowMode _modes[LineType::Nb_Types];
  DebugLevel _debugLevel;

  virtual void updateDebugLevel() {}
  virtual void doLog(LineType type, const TQString &text, Action action) = 0;
  virtual void doLog(DebugLevel level, const TQString &text, Action action) = 0;
};

//-----------------------------------------------------------------------------
class StringView : public View
{
public:
  StringView() {}
  TQString string() const { return _s; }
  virtual void appendToLastLine(const TQString &text) { _s += text; }
  virtual void clear() { _s = TQString(); }
  virtual void sorry(const TQString &message, const TQString &details);
  virtual bool askContinue(const TQString &message);

private:
  TQString _s;

  virtual void doLog(LineType, const TQString &text, Action) { _s += text + "\n"; }
  virtual void doLog(DebugLevel, const TQString &text, Action) { _s += text + "\n"; }
};

//-----------------------------------------------------------------------------
class Base : public Generic
{
public:
  Base(Base *parent = 0);
  virtual ~Base();
  void setParent(Base *parent);
  void setView(View *view);
  View *view() { return logData()->view; }

  virtual void log(LineType type, const TQString &message, Action action = Immediate);
  virtual void log(DebugLevel level, const TQString &message, Action action = Immediate);
  virtual void appendToLastLine(const TQString &text);
  void setError(const TQString &error) { logData()->error = error; }
  virtual bool hasError() const { return !logData()->error.isNull(); }
  virtual TQString error() const { return logData()->error; }
  virtual void resetError() { logData()->error = TQString(); }
  virtual void sorry(const TQString &message, const TQString &details = TQString());
  virtual bool askContinue(const TQString &message);
  virtual void clear();
  void logUserAbort();

protected:
  Base *_parent;
  class LogData {
  public:
    LogData() : view(0) {}
    TQString error;
    View *view;
  };
  LogData *_data;
  LogData *logData() { return _parent ? _parent->logData() : _data; }
  const LogData *logData() const { return _parent ? _parent->logData() : _data; }
};

class KeyList {
public:
  KeyList(const TQString &title = TQString()) : _title(title) {}
  void setTitle(const TQString &title) { _title = title; }
  void append(const TQString &key, const TQString &label) { _keys += key; _labels += label; }
  TQString text() const;
  void display(Generic &log) const;

private:
  TQString     _title;
  TQStringList _keys, _labels;
};

} // namespace

#endif
