/****************************************************************************
*
*                                 M U E S L I   v 1.8
*
*
*     Copyright 2020 IMDEA Materials Institute, Getafe, Madrid, Spain
*     Contact: muesli.materials@imdea.org
*     Author: Ignacio Romero (ignacio.romero@imdea.org)
*
*     This file is part of MUESLI.
*
*     MUESLI 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 3 of the License, or
*     (at your option) any later version.
*
*     MUESLI 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 MUESLI.  If not, see <http://www.gnu.org/licenses/>.
*
****************************************************************************/



#include "damage.h"
#include <string>
#include <map>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <cstdarg>
#include <cstdio>
#include <cstring>
#include <sstream>
#include <stdexcept>

using namespace muesli;


std::ostream* damageModel::damageLog(0);


damageModel::damageModel() :
_name("unnamed damage model")
{
    if (damageLog == 0) damageLog = &(std::cout);
}




damageModel::damageModel(const std::string& name) :
_name(name)
{
    if (damageLog == 0) damageLog = &(std::cout);
}




damageModel::damageModel(const std::string& name,
                     const materialProperties& cl)
:
_name(name)
{
    if (damageLog == 0) damageLog = &(std::cout);
}




damageModel::~damageModel()
{}




std::ostream& damageModel::damageModel::getLogger()
{
    if (damageLog == 0) damageLog = &(std::cout);
    return *damageLog;
}




bool damageModel::check() const
{
    bool isok = true;

    if (_name.empty()) isok = false;

    return isok;
}




void damageModel::setLogger(std::ostream &of)
{
    damageModel::damageLog = &of;
}




void  damageModelDB::addDamageModel(const size_t label, damageModel& dm)
{
    theDB[label] = &dm;
}




void damageModelDB::free()
{
    for (auto dm : theDB) delete dm.second;
}




damageModelDB& damageModelDB::getDB()
{
    static damageModelDB instance;
    return instance;
}




/* retrieves a material structure given its number in the static list of materials */
damageModel& damageModelDB::getDamageModel(const size_t label) const
{
    std::map<size_t,damageModel*>::const_iterator iter = theDB.find(label);

    if (iter == theDB.end())
    {
        std::ostream& mlog = damageModel::getLogger();
        mlog << "Damage model with label " << label << " not defined";
    }
    return *(iter->second);
}




damageModel& damageModelDB::getDamageModel(const std::string& name) const
{
    damageModel *s(0);
    std::map<size_t,damageModel*>::const_iterator iter = theDB.begin();

    while( iter != theDB.end() )
    {
        if ( iter->second->name() == name)
        {
            s = iter->second;
            break;
        }
        ++iter;
    }

    if (s == 0) throw std::runtime_error("Damage model not found in global list.");
    return *s;
}




void damageModelDB::print(std::ostream &of) const
{
    of << "\n\n\n\n                D a m a g e  m o d e l s  (" << theDB.size() << ")";
    for (auto dm : theDB)
    {
        of << "\n\nMaterial #" << dm.first << ": " << dm.second->name();
        dm.second->print(of);
    }
}
