/* ====================================================================
 * Copyright (c) 2003-2008  Martin Hauner
 *                          http://subcommander.tigris.org
 *
 * Subcommander is licensed as described in the file doc/COPYING, which
 * you should have received as part of this distribution.
 * ====================================================================
 */

//sc
#include "ConfigManager.h"
#include "config.cpp"
#include "ColorId.h"
#include "sublib/Utility.h"
#include "sublib/ColorStorage.h"
#include "sublib/settings/LayoutSettingsHandler.h"
#include "sublib/config/ConfigFile.h"
#include "sublib/config/ConfigData.h"

// qt
#include <QtCore/QString>
#include <QtCore/QRegExp>
#include <QtGui/QApplication>


// option strings
static sc::String OptWhitespacesId("option.whitespaces");


ConfigManager::ConfigManager()
: _dbgDump(false)
{
  _file = new ConfigFile( sc::String("sm.ini"), defaultConf, sizeof(defaultConf) );
  _cfg = new ConfigData( _file );
}

ConfigManager::~ConfigManager()
{
  delete _cfg;
  delete _file;
}

void ConfigManager::load()
{
  _cfg->load();

  // init colors
  Colors colors;
  getColors(colors);
  ColorStorage::setColors(colors);
}

void ConfigManager::save()
{
  clean();
  _cfg->save();
}

QFont ConfigManager::getGeneralFont()
{
  ConfigValue fontString = _cfg->getValue( sc::String("font.general") );

  if( fontString.isNull() )
  {
    return qApp->font();
  }

  QFont font;
  font.fromString( (const char*)fontString.getStringValue() );
  return font;
}

void ConfigManager::setGeneralFont( const QFont& font )
{
  if( QApplication::font() != font )
  {
    ConfigValues values;
    values.push_back( ConfigValue(sc::String("font.general"),sc::String(font.toString())) );
    _cfg->setValues( sc::String("font.general"), values );

    QApplication::setFont( font, true );
  }
}

QFont ConfigManager::getEditorFont()
{
  ConfigValue fontString = _cfg->getValue( sc::String("font.editor") );

  if( fontString.isNull() )
  {
#if _WIN32
    return QFont( "Courier New" , 9, QFont::Normal, false );
#elif _MACOSX
    return QFont( "Andale Mono" , 12, QFont::Normal, false );
#else // Unix/Linux
    return QFont( "Courier New" , 9, QFont::Normal, false );
#endif
  }

  QFont font;
  font.fromString( (const char*)fontString.getStringValue() );
  return font;
}

void ConfigManager::setEditorFont( const QFont& font )
{
  ConfigValues values;
  values.push_back( ConfigValue(sc::String("font.editor"),sc::String(font.toString())) );
  _cfg->setValues( sc::String("font.editor"), values );

  //doesn't work as expected, this will change the font of any _new_ QTextEdit
  //to the given font but not the currently open ones.
  QApplication::setFont( font, true, "TextWidget" );
  QApplication::setFont( font, true, "TextGlueWidget" );
  QApplication::setFont( font, true, "TextLineNrWidget" );
}


Color ConfigManager::getColor( long id, const sc::String& name, const QColor& def,
  const sc::String& desc )
{
  ConfigValue color = _cfg->getValue( name );
  if( color.isNull() )
  {
    return Color( id, (const char*)name, def, (const char*)desc );
  }

  return Color( id, QString::fromUtf8(color.getKey()),QColor(color.getStringValue()),
    (const char*)desc );
}

void ConfigManager::getColors( Colors& colors )
{
  // TextWidget Colors
  colors.push_back( getColor( ColorTextFg,                  sc::String("color.text.fg"),
    QColor(000,000,000), sc::String("-") ) );

  colors.push_back( getColor( ColorWhitespaceFg,            sc::String("color.whitespace.fg"),
    QColor(200,200,200), sc::String("-") ) );

  colors.push_back( getColor( ColorNormalBg,                sc::String("color.normal.bg"),
    QColor(255,255,255), sc::String("-") ) );

  colors.push_back( getColor( ColorNopBg,                   sc::String("color.nop.bg"),
    QColor(250,250,250), sc::String("-") ) );

  colors.push_back( getColor( ColorMergedBg,                sc::String("color.merged.bg"),
    QColor(220,230,255), sc::String("-") ) );

  colors.push_back( getColor( ColorHighlightedBg,           sc::String("color.highlighted.bg"),
    QColor(0,0,100), sc::String("-") ) );

  colors.push_back( getColor( ColorHighlightedTextFg,       sc::String("color.highlighted.text.fg"),
    QColor(255,255,255), sc::String("-") ) );

  colors.push_back( getColor( ColorHighlightedWhitespaceFg, sc::String("color.highlighted.whitespace.fg"),
    QColor(100,100,120), sc::String("-") ) );

  // Conflict Colors
  colors.push_back( getColor( ColorConflictBgAll,            sc::String("color.conflict.bg.all"),
    QColor(255,210,210), sc::String("-") ) );

  colors.push_back( getColor( ColorConflictBgModifiedLatest, sc::String("color.conflict.bg.modifiedlatest"),
    QColor(210,255,210), sc::String("-") ) );

  colors.push_back( getColor( ColorConflictBgLatestModified, sc::String("color.conflict.bg.latestmodified"),
    QColor(210,255,210), sc::String("-") ) );

  colors.push_back( getColor( ColorConflictBgOriginal,       sc::String("color.conflict.bg.original"),
    QColor(210,255,210), sc::String("-") ) );

  // TextLineNrWidget
  colors.push_back( getColor( ColorLineNrBg,                sc::String("color.linenr.bg"),
    QColor(240,240,240), sc::String("-") ) );

  colors.push_back( getColor( ColorLineNrFg,                sc::String("color.linenr.fg"),
    QColor(120,120,120), sc::String("-") ) );

  // misc
  colors.push_back( getColor( ColorDashBg,                  sc::String("color.dash.bg"),
    QColor(255,255,255), sc::String("-") ) );

  colors.push_back( getColor( ColorDashFg,                  sc::String("color.dash.fg"),
    QColor(150,150,150), sc::String("-") ) );
}

void ConfigManager::setColors( const Colors& colors )
{
  ConfigValues values;

  for( Colors::const_iterator it = colors.begin(); it != colors.end(); it++ )
  {
    const Color& c = *it;
    values.push_back( 
      ConfigValue( sc::String(c._name.utf8()),sc::String(c._color.name())) );
  }

  _cfg->setValues( sc::String("color."), values );

  ColorStorage::setColors(colors);

  // refresh the whole app
  qApp->mainWidget()->hide();
  qApp->mainWidget()->show();
}

bool ConfigManager::getDump()
{
  return _dbgDump;
}

void ConfigManager::setDump(bool b)
{
  _dbgDump = b;
  setDumpOnException(b);
}

bool ConfigManager::getLog()
{
  return false;
}

void ConfigManager::setLog(bool b)
{
  // nop
}

bool ConfigManager::getL10n()
{
  ConfigValue option = _cfg->getValue(DebugL10n);

  if( option.isNull() )
  {
    return true;
  }

  return option.getBoolValue();
}

void ConfigManager::setL10n(bool b)
{
  ConfigValue value(DebugL10n,b);

  ConfigValues values;
  values.push_back( value );
  _cfg->setValues( value.getKey(), values );
}

bool ConfigManager::getOptWhitespace() const
{
  ConfigValue option = _cfg->getValue( OptWhitespacesId );

  if( option.isNull() )
  {
    return false;
  }

  return option.getBoolValue();
}

void ConfigManager::setOptWhitespace( bool b )
{
  ConfigValue value(OptWhitespacesId,b);

  ConfigValues values;
  values.push_back( value );
  _cfg->setValues( value.getKey(), values );
}

int ConfigManager::getValue( const QString& key, int def )
{
  return LayoutSettingsHandler::getValue(
    _cfg, QString("layout.value.%1").arg(key), def );
}

void ConfigManager::setValue( const QString& key, int value )
{
  LayoutSettingsHandler::setValue(
    _cfg, QString("layout.value.%1").arg(key), value );
}

QSize ConfigManager::getSize( const QString& key, const QSize& def )
{
  return LayoutSettingsHandler::getSize(
    _cfg, QString("layout.size.%1").arg(key), def );
}

void ConfigManager::setSize( const QString& key, const QSize& size )
{
  LayoutSettingsHandler::setSize(
    _cfg, QString("layout.size.%1").arg(key), size );
}

QRect ConfigManager::getRect( const QString& key, const QRect& def )
{
  return LayoutSettingsHandler::getRect(
    _cfg, QString("layout.%1.rect").arg(key), def );
}

void ConfigManager::setRect( const QString& key, const QRect& rect )
{
  LayoutSettingsHandler::setRect(
    _cfg, QString("layout.%1.rect").arg(key), rect );
}

QByteArray ConfigManager::getByteArray( const QString& key, const QByteArray& def )
{
  return LayoutSettingsHandler::getByteArray(
    _cfg, QString("layout.%1").arg(key), def );
}

void ConfigManager::setByteArray( const QString& key, const QByteArray& bytearray )
{
  LayoutSettingsHandler::setByteArray(
    _cfg, QString("layout.%1").arg(key), bytearray );
}

void ConfigManager::getHeaderColumns( const QString& key, Q3Header* header )
{
  LayoutSettingsHandler::getHeaderColumns( 
    _cfg, QString("layout.header.%1").arg(key), header );
}

void ConfigManager::setHeaderColumns( const QString& key, const Q3Header* header )
{
  LayoutSettingsHandler::setHeaderColumns(
    _cfg, QString("layout.header.%1").arg(key), header );
}

void ConfigManager::clean()
{
  // obsolete since 2.0.0
  _cfg->delValues( sc::String("layout.rect") );

  // obsolete since 2.0.0 b5
  _cfg->delValues( sc::String("layout.main.rect") );
  _cfg->delValues( sc::String("layout.value.main.maximized") );
}

