/***************************************************************************
                          Project.cpp  -  description
                             -------------------
    begin                : jeu jui 3 2003
    copyright            : (C) 2003 by Alain Gibaud
    email                : alain.gibaud@univ-valenciennes.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 "Project.h"
#include <kurl.h>
#include <qurl.h>
#include <qstringlist.h>
#include <qfileinfo.h>
#include <qdatetime.h>

#include "FNU.h"

#include <iostream>
using namespace std ;

Project::Project(const QString& projectfile)
{
  config = new KConfig(projectfile, false, false) ;
  if(config) projectFileName = projectfile ;  
}
Project::~Project()
{
  if(config)
  {
		commit() ;
		delete config ;
  }
}
/** Add a new file to this project */
void Project::addFile(const QString& filename)
{
  QStringList files = getFiles() ;
  files += filename  ;
  config->writeEntry( "inputFiles" , files) ;
  commit() ;
}
/** Remove a file from the project */
void Project::removeFile(const QString& filename)
{
  QStringList files = getFiles() ;
  files.remove(filename)  ;
  config->writeEntry( "inputFiles" , files) ;
  commit() ;
}
/** Returns the project base directory (extracted from the project file name)
	with a trailing "/"
 */
QString Project::projectPath()
{
    QUrl url(projectFileName) ;
    return url.dirPath()+"/" ;
}
/** Set the short description for this project */
void Project::setDescription(const QString& desc)
{
  config->setGroup("General") ;
  config->writeEntry("description", desc) ;
  commit() ;
}
/** Set the version id for this project */
void Project::setVersion(const QString& ver)
{
  config->setGroup("General") ;
  config->writeEntry("version", ver) ;
  commit() ;
}
/** Set the type for this project */
void Project::setType(const QString& t)
{
  config->setGroup("General") ;
  config->writeEntry("type", t) ;
  commit() ;
}
/** Set the output file (.hex) for this project */
void Project::setOutput(const QString& out)
{
  config->setGroup("General") ;
  config->writeEntry("output", out) ;
  commit() ;
}
/** flush the current project to the project file
 */
void Project::commit()
{
  config->sync() ;
}
/** restore the current project from project file */
void Project::restore()
{
  config->deleteGroup("General",true) ;
  config->deleteGroup("Files",true) ;
  config->reparseConfiguration() ;
}
/** Simplify a path+file name, to make it relative to the project filename */
// a debugger
QString Project::projectRelative(const QString& filename)
{
  QString pp =  projectPath() , r = filename ;
  int i = r.find(pp)   ;
  if( i == 0 ) // project path found at the begining of filename
      r =  r.right(filename.length()-pp.length()) ;
  return r ;
}
/** Generates an absolute filename from a project relative name
(absolute names remain unchanged)
*/
QString Project::absFilename(const QString &fn)
{
	return ( fn[0] == '/') ?  fn  : projectPath()+fn ;
}
/** Returns the list of files used in the project */
QStringList Project::getFiles()
{
  config->setGroup("Files") ;
  return config->readListEntry("inputFiles") ;
}
/** Returns the list of absolute file names  used in the project */
QStringList Project::getAbsFiles()
{
  QString proj_path = FNU:: path(projectFileName), f ;
  QStringList files(getFiles()), abs_files  ;

  for(QStringList::iterator  i = files.begin() ; i  !=  files.end() ; ++i)
  {
    abs_files += absFilename(*i)  ;
  }
  return abs_files ;
}

/** Returns the project name 
    (ie: naked project file name)
 */
QString Project::projectName()
{
  return FNU::file(projectFileName) ;
}
/** Returns true if absolute filename af is already in the project 
filename list. */
bool Project::absFileExists(const QString &af)
{
	QStringList files(getAbsFiles())  ;
  for(QStringList::iterator  i = files.begin() ; i  !=  files.end() ; ++i)
  {
    if( *i == af) return true  ;
  }
  return false ;
}
/** No descriptions */
QString Project::getVersion()
{
	config->setGroup("General") ;
  return config->readEntry("version","0.1") ;
}
/** No descriptions */
QString Project::getType()
{
	config->setGroup("General") ;
  return config->readEntry("type","asm") ;
}
/** No descriptions */
QString Project::getDescription()
{
	config->setGroup("General") ;
  return config->readEntry("description","<none>") ;
}
/** No descriptions */
QString Project::getDevice()
{
	config->setGroup("Assembler") ;
  return config->readEntry("target-device","p12c508") ;
}
void Project::setDevice(const QString& x)
{
	config->setGroup("Assembler") ;
  config->writeEntry("target-device",x) ;
}

/** No descriptions */
QString Project::getRadix()
{
	config->setGroup("Assembler") ;
  return config->readEntry("radix","dec") ;
}
void Project::setRadix(const QString& x)
{
	config->setGroup("Assembler") ;
  config->writeEntry("radix",x) ;
}
/** No descriptions */
QString Project::getWarnLevel()
{
	config->setGroup("Assembler") ;
  return config->readEntry("warn-level","2") ;
}
void Project::setWarnLevel(const QString& x)
{
	config->setGroup("Assembler") ;
  config->writeEntry("warn-level",x) ;
}
/** No descriptions */
QString Project::getIncludeDir()
{
	config->setGroup("Assembler") ;
  return config->readEntry("include-dir","") ;
}
void Project::setIncludeDir(const QString& x)
{
	config->setGroup("Assembler") ;
  config->writeEntry("include-dir",x) ;
}
/** No descriptions */
QString Project::getCIncludeDir()
{
	config->setGroup("C") ;
  return config->readEntry("include-dir","") ;
}
void Project::setCIncludeDir(const QString& x)
{
	config->setGroup("C") ;
  config->writeEntry("include-dir",x) ;
}
/** No descriptions */
QString Project::getCCompiler()
{
	config->setGroup("C") ;
  return config->readEntry("compiler","cpik") ;
}
void Project::setCCompiler(const QString& x)
{
	config->setGroup("C") ;
  config->writeEntry("compiler",x) ;
}
/** No descriptions */
QString Project::getCLibsDir()
{
	config->setGroup("C") ;
  return config->readEntry("libs-dir","") ;
}
void Project::setCLibsDir(const QString& x)
{
	config->setGroup("C") ;
  config->writeEntry("libs-dir",x) ;
}
/** No descriptions */
QString Project::getOtherOptions()
{
	config->setGroup("Assembler") ;
  return config->readEntry("other-options","") ;
}
void Project::setOtherOptions(const QString& x)
{
	config->setGroup("Assembler") ;
  config->writeEntry("other-options",x) ;
}

/** No descriptions */
QString Project::getOtherCOptions()
{
	config->setGroup("C") ;
  return config->readEntry("other-options","") ;
}
void Project::setOtherCOptions(const QString& x)
{
	config->setGroup("C") ;
  config->writeEntry("other-options",x) ;
}

/** No descriptions */
bool Project::getCSlb()
{
	config->setGroup("C") ;
  return config->readBoolEntry("slb",false) ;
}
void Project::setCSlb(bool x)
{
	config->setGroup("C") ;
  config->writeEntry("slb",x) ;
}

/** No descriptions */
bool Project::getCAsm()
{
	config->setGroup("C") ;
  return config->readBoolEntry("asm",false) ;
}
void Project::setCAsm(bool x)
{
	config->setGroup("C") ;
  config->writeEntry("asm",x) ;
}

/** No descriptions */
bool Project::getAsmList()
{
	config->setGroup("Assembler") ;
  return config->readBoolEntry("list",false) ;
}
void Project::setAsmList(bool x)
{
	config->setGroup("Assembler") ;
  config->writeEntry("list",x) ;
}

/** No descriptions */
bool Project::getLinkDebug()
{
	config->setGroup("Linker") ;
  return config->readBoolEntry("debug",false) ;
}
void Project::setLinkDebug(bool x)
{
	config->setGroup("Linker") ;
  config->writeEntry("debug",x) ;
}

/** No descriptions */
bool Project::getLinkMap()
{
	config->setGroup("Linker") ;
  return config->readBoolEntry("map",false) ;
}
void Project::setLinkMap(bool x)
{
	config->setGroup("Linker") ;
  config->writeEntry("map",x) ;
}


/** No descriptions */
QString Project::getHexFormat()
{
	config->setGroup("Linker") ;
  return config->readEntry("hex-format","inhx32") ;
}
void Project::setHexFormat(const QString& x)
{
	config->setGroup("Linker") ;
  config->writeEntry("hex-format",x) ;
}
/** No descriptions */
QString Project::getLibsDir()
{
	config->setGroup("Linker") ;
  return config->readEntry("objs-libs-dir","") ;
}
void Project::setLibsDir(const QString& x)
{
	config->setGroup("Linker") ;
  config->writeEntry("objs-libs-dir",x) ;
}

/** Linker script file */
QString Project::getLinkScript()
{
  config->setGroup("Linker") ;
  return projectPath( ) + config->readEntry("linker-script","") ;
}
void Project::setLinkScript(const QString &)
{
  config->setGroup("Linker") ;
  config->writeEntry("linker-script","") ;
}

/** No descriptions */
QString Project::getOtherLinkOptions()
{
	config->setGroup("Linker") ;
  return config->readEntry("other-options","") ;
}
void Project::setOtherLinkOptions(const QString& x)
{
	config->setGroup("Linker") ;
  config->writeEntry("other-options",x) ;
}
/** No descriptions */
QString Project::projectPathFileName()
{
  return projectFileName ;
}
/** Compute hex file name from project file name
 */
QString Project::getHexName()
{
  return  FNU::changeExt(  projectPathFileName(), "hex")  ;
}
/** Compute asm file name from project file name
 */
QString Project::getAsmName()
{
  return  FNU::changeExt(  projectPathFileName(), "asm")  ;
}
/** true if the project contains  C source/header file(s).  */
bool Project::isCproject()
{
//  QStringList files=getFiles() ;
//  for(QStringList::iterator  i = files.begin() ; i  !=  files.end() ; ++i)
//  {
//    if( FNU::isCSource(*i) || FNU::isCHeader(*i)) return true  ;
//  }

  return getType() == "C" ;
}
