/***************************************************************************
 *   Copyright (C) 2006 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.                                   *
 ***************************************************************************/
#include "compile_config.h"

#include "common/global/generic_config.h"
#include "devices/list/device_list.h"
#include "libgui/project.h"
#include "tool_list.h"

//----------------------------------------------------------------------------
PURL::Directory Compile::Config::directory(const Tool::Group &group, DirectoryType type)
{
  TQString def;
  if ( type!=DirectoryType::Executable )
    def = group.autodetectDirectory(type, directory(group, DirectoryType::Executable), withWine(group)).path();
  return PURL::Directory(value(group.name(), TQString(), type.key() + TQString("_path"), def));
}
void Compile::Config::setDirectory(const Tool::Group &group, DirectoryType type, const PURL::Directory &dir)
{
  setValue(group.name(), TQString(), type.key() + TQString("_path"), dir.path());
  if ( type==DirectoryType::Executable ) const_cast<Tool::Group &>(group).init();
}

bool Compile::Config::withWine(const Tool::Group &group)
{
  TQString def = (group.preferedExecutableType()==Tool::ExecutableType::Unix ? "false" : "true");
  return ( value(group.name(), TQString(), "with_wine", def)=="true" );
}
void Compile::Config::setWithWine(const Tool::Group &group, bool withWine)
{
  setValue(group.name(), TQString(), "with_wine", withWine ? "true" : "false");
  const_cast<Tool::Group &>(group).init();
}

Tool::OutputExecutableType Compile::Config::outputExecutableType(const Tool::Group &group)
{
  TQString s = value(group.name(), TQString(), "output_type", Tool::OutputExecutableType(Tool::OutputExecutableType::Coff).key());
  return Tool::OutputExecutableType::fromKey(s);
}
void Compile::Config::setOutputExecutableType(const Tool::Group &group, Tool::OutputExecutableType type)
{
  setValue(group.name(), TQString(), "output_type", type.key());
  const_cast<Tool::Group &>(group).init();
}

TQString Compile::Config::value(const TQString &group, const TQString &subGroup, const TQString &key, const TQString &defaultValue)
{
  TQString grp = (subGroup.isEmpty() ? group : group + '-' + subGroup);
  GenericConfig gc(grp);
  return gc.readEntry(key, defaultValue);
}
void Compile::Config::setValue(const TQString &group, const TQString &subGroup, const TQString &key, const TQString &value)
{
  TQString grp = (subGroup.isEmpty() ? group : group + '-' + subGroup);
  GenericConfig gc(grp);
  gc.writeEntry(key, value);
}
TQStringList Compile::Config::listValues(const TQString &group, const TQString &subGroup, const TQString &key, const TQStringList &defaultValues)
{
  TQString grp = (subGroup.isEmpty() ? group : group + '-' + subGroup);
  GenericConfig gc(grp);
  return gc.readListEntry(key, defaultValues);
}
void Compile::Config::setListValues(const TQString &group, const TQString &subGroup, const TQString &key, const TQStringList &values)
{
  TQString grp = (subGroup.isEmpty() ? group : group + '-' + subGroup);
  GenericConfig gc(grp);
  gc.writeEntry(key, values);
}

TQStringList Compile::Config::includeDirs(Tool::Category category, const TQString &prefix, const TQString &suffix, const TQString &separator) const
{
  TQStringList list;
  TQStringList raw = rawIncludeDirs(category);
  for (uint i=0; i<raw.size(); i++) {
    if ( separator.isEmpty() ) list.append(prefix + raw[i] + suffix);
    else if ( i==0 ) list.append(prefix + raw[i]);
    else list[0] += separator + raw[i];
  }
  if ( !separator.isEmpty() && list.count()!=0 ) list[0] += suffix;
  return list;
}

HexBuffer::Format Compile::Config::hexFormat() const
{
  TQString s = value(Tool::Category::Linker, "format", HexBuffer::FORMATS[HexBuffer::IHX32]);
  for (uint i=0; i<HexBuffer::Nb_Formats; i++)
    if ( s==HexBuffer::FORMATS[i] ) return HexBuffer::Format(i);
  return HexBuffer::Nb_Formats;
}
void Compile::Config::setHexFormat(HexBuffer::Format f)
{
  TQString s = (f==HexBuffer::Nb_Formats ? 0 : HexBuffer::FORMATS[f]);
  setValue(Tool::Category::Linker, "format", s);
}

TQString Compile::Config::device(const Project *project)
{
  TQString device = globalValue(project, "device", TQString());
  return Device::lister().checkName(device);
}

const Tool::Group &Compile::Config::toolGroup(const Project *project)
{
  TQString s = globalValue(project, "tool", TQString());
  const Tool::Group *group = Tool::lister().group(s);
  if ( group==0 ) return *Tool::lister().begin().data();
  return *group;
}

TQStringList Compile::Config::customOptions(Tool::Category category) const
{
  return TQStringList::split(' ', rawCustomOptions(category));
}

TQStringList Compile::Config::customLibraries(Tool::Category category) const
{
  return TQStringList::split(' ', rawCustomLibraries(category));
}

void Compile::Config::setValue(Tool::Category category, const TQString &key, const TQString &value)
{
  Q_ASSERT( category!=Tool::Category::Nb_Types );
  Q_ASSERT( _project || _group );
  if (_project) _project->setValue(category.key(), key, value);
  else Config::setValue(_group->name(), category.key(), key, value);
}
TQString Compile::Config::value(Tool::Category category, const TQString &key, const TQString &defaultValue) const
{
  Q_ASSERT( category!=Tool::Category::Nb_Types );
  Q_ASSERT( _project || _group );
  if (_project) return _project->value(category.key(), key, defaultValue);
  return Config::value(_group->name(), category.key(), key, defaultValue);
}
void Compile::Config::setListValues(Tool::Category category, const TQString &key, const TQStringList &values)
{
  Q_ASSERT( category!=Tool::Category::Nb_Types );
  Q_ASSERT( _project || _group );
  if (_project) _project->setListValues(category.key(), key, values);
  else Config::setListValues(_group->name(), category.key(), key, values);
}
TQStringList Compile::Config::listValues(Tool::Category category, const TQString &key, const TQStringList &defaultValues) const
{
  Q_ASSERT( category!=Tool::Category::Nb_Types );
  Q_ASSERT( _project || _group );
  if (_project) return _project->listValues(category.key(), key, defaultValues);
  return Config::listValues(_group->name(), category.key(), key, defaultValues);
}
bool Compile::Config::boolValue(Tool::Category category, const TQString &key, bool defaultValue) const
{
  TQString s = value(category, key, TQString());
  if ( s.isNull() ) return defaultValue;
  return !( s=="false" || s=="0" );
}
uint Compile::Config::uintValue(Tool::Category category, const TQString &key, uint defaultValue) const
{
  bool ok;
  uint i = value(category, key, TQString()).toUInt(&ok);
  if ( !ok ) return defaultValue;
  return i;
}

TQString Compile::Config::globalValue(const Project *project, const TQString &key, const TQString &defaultValue)
{
  if (project) return project->value("general", key, defaultValue);
  return Config::value("general", TQString(), key, defaultValue);
}
void Compile::Config::setGlobalValue(Project *project, const TQString &key, const TQString &value)
{
  if (project) project->setValue("general", key, value);
  else Config::setValue("general", TQString(), key, value);
}

TQStringList Compile::Config::globalListValues(const Project *project, const TQString &key, const TQStringList &defaultValues)
{
  if (project) return project->listValues("general", key, defaultValues);
  return Config::listValues("general", TQString(), key, defaultValues);
}
void Compile::Config::setGlobalListValues(Project *project, const TQString &key, const TQStringList &values)
{
  if (project) project->setListValues("general", key, values);
  else Config::setListValues("general", TQString(), key, values);
}
