/*
 *  model.cpp
 *
 *  This file is part of NEST.
 *
 *  Copyright (C) 2004 The NEST Initiative
 *
 *  NEST 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.
 *
 *  NEST 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 NEST.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "model.h"
#include "exceptions.h"
#include "dictutils.h"
#include "nestmodule.h"
#include <algorithm>

namespace nest
{

  Model::Model(const std::string& name)
    : name_(name),
      memory_()
  {}
  
  void Model::set_threads()
  {
    set_threads_(NestModule::get_num_threads());
  }
  
  void Model::set_threads_(thread t)
  {
    for (size_t i = 0; i < memory_.size(); ++i)
      if ( memory_[i].get_instantiations() > 0 )
	throw KernelException();

    std::vector<sli::pool> tmp(t); 
    memory_.swap(tmp);

    for (size_t i = 0; i < memory_.size(); ++i)
      init_memory_(memory_[i]);
  }

  void Model::reserve(thread t, size_t s)
  {
    assert((size_t)t < memory_.size());    
    memory_[t].reserve(s);
  }

  void Model::clear()
  {
    std::vector<sli::pool> mem;
    memory_.swap(mem);
    set_threads_(1);
  }

  size_t Model::mem_available()
  {
    size_t result = 0;
    for (size_t t = 0; t < memory_.size(); ++t)
      result += memory_[t].available();
    
    return result;
  }

  size_t Model::mem_capacity()
  {
    size_t result = 0;
    for (size_t t = 0; t < memory_.size(); ++t)
      result += memory_[t].get_total();

    return result;
  }

  void Model::set_status(DictionaryDatum d)
  {
    set_status_(d);
  }

  DictionaryDatum Model::get_status(void)
  {
    DictionaryDatum d=get_status_();
    
    std::vector<long> tmp(memory_.size());
    for(size_t t=0; t< tmp.size(); ++t)
      tmp[t]= memory_[t].get_instantiations();

    (*d)["instantiations"]= Token(tmp);
    (*d)["type_id"]= LiteralDatum(Node::network()->get_model(type_id_)->get_name());

    for(size_t t=0; t< tmp.size(); ++t)
      tmp[t]= memory_[t].get_total();

    (*d)["capacity"]=Token(tmp);

    for(size_t t=0; t< tmp.size(); ++t)
      tmp[t]= memory_[t].available();

    (*d)["available"]= Token(tmp);

    (*d)["model"]=LiteralDatum(get_name());
    return d;
  }

} // namespace