/*
 * Project: MoleCuilder
 * Description: creates and alters molecular systems
 * Copyright (C)  2013 University of Bonn. All rights reserved.
 * Copyright (C)  2013 Frederik Heber. All rights reserved.
 * 
 *
 *   This file is part of MoleCuilder.
 *
 *    MoleCuilder 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.
 *
 *    MoleCuilder is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with MoleCuilder.  If not, see .
 */
/*
 * FragmentJobQueue.cpp
 *
 *  Created on: Mar 4, 2013
 *      Author: heber
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
#include "CodePatterns/MemDebug.hpp"
#include "Fragmentation/Automation/FragmentJobQueue.hpp"
#include 
#include 
#include "CodePatterns/Assert.hpp"
#include "CodePatterns/Log.hpp"
#include "CodePatterns/Singleton_impl.hpp"
#include "Box.hpp"
#include "Fragmentation/parseKeySetFile.hpp"
#include "Helpers/defs.hpp"
#include "Jobs/MPQCJob.hpp"
#include "LinearAlgebra/RealSpaceMatrix.hpp"
#include "World.hpp"
void FragmentJobQueue::parsejob(const std::string &filename, const unsigned int level)
{
  std::ifstream file;
  file.open(filename.c_str());
  ASSERT( file.good(), "parsejob() - file "+filename+" does not exist.");
  std::string output((std::istreambuf_iterator(file)),
      std::istreambuf_iterator());
  // determine number of lines as an approximation to priority of job
  size_t pos = 0;
  size_t newlines = 0;
  while ((pos = output.find('\n', pos+1)) != std::string::npos)
    ++newlines;
  // get domain size and alikes for density sampling
  double begin[NDIM] = { 0., 0., 0. };
  RealSpaceMatrix M = World::getInstance().getDomain().getM();
  M *= 1./AtomicLengthToAngstroem;  // scale to atomic length units
  const double size = M.at(0,0);
  double end[NDIM] = { size, size, size };
  ASSERT( M.determinant() == size*size*size,
      "parsejob() - current domain matrix "+toString(M)+" is not cubic.");
  // create job
  FragmentJob::ptr testJob( new MPQCJob(JobId::IllegalJob, output, begin, end, level) );
  testJob->setPriority(newlines);
  jobs.push_back(testJob);
  file.close();
  LOG(1, "INFO: Added MPQCCommandJob from file "+filename+" with priority "
      +toString(newlines)+".");
}
bool FragmentJobQueue::addJobsFromFiles(
    const std::vector< boost::filesystem::path > &jobfiles, const unsigned int level)
{
  for (std::vector< boost::filesystem::path >::const_iterator iter = jobfiles.begin();
      iter != jobfiles .end(); ++iter) {
    const std::string &filename = (*iter).string();
    if (boost::filesystem::exists(filename)) {
      LOG(1, "INFO: Creating MPQCCommandJob with filename'"+filename+"'.");
      parsejob(filename, level);
    } else {
      ELOG(1, "Fragment job "+filename+" does not exist.");
      return false;
    }
  }
  return true;
}
bool FragmentJobQueue::addKeySetsFromFiles(
    const boost::filesystem::path &path,
    const size_t FragmentCounter,
    const enum KeySetFileType keysettype
    )
{
  const size_t NoJobs = KeySets.KeySets.size();
  parseKeySetFile(KeySets, path.string(), FragmentCounter, NonHydrogenKeySets);
  ASSERT( (KeySets.KeySets.size()-NoJobs) == FragmentCounter,
      "FragmentJobQueue::addKeySetsFromFiles() - mismatching number of new fragments "
      +toString(KeySets.KeySets.size()-NoJobs)+" and number of Keyset "
      +toString(FragmentCounter)+".");
  return (KeySets.KeySets.size() > NoJobs);
}
bool FragmentJobQueue::addFullKeySetsFromFiles(
    const boost::filesystem::path &path,
    const size_t FragmentCounter,
    const enum KeySetFileType keysettype
    )
{
  const size_t NoJobs = FullKeySets.KeySets.size();
  parseKeySetFile(FullKeySets, path.string(), FragmentCounter, NonHydrogenKeySets);
  ASSERT( (FullKeySets.KeySets.size()-NoJobs) == FragmentCounter,
      "FragmentJobQueue::addKeySetsFromFiles() - mismatching number of fragments "
      +toString(FullKeySets.KeySets.size()-NoJobs)+" and number of FullKeyset "
      +toString(FragmentCounter)+".");
  return (FullKeySets.KeySets.size() > NoJobs);
}
void FragmentJobQueue::clear()
{
  jobs.clear();
  KeySets.clear();
  FullKeySets.clear();
}
CONSTRUCT_SINGLETON(FragmentJobQueue)