/*
 * Copyright (c) 2015, University of Kaiserslautern
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors:
 *    Eder F. Zulian
 *    Matthias Jung
 */

#ifndef THERMALSIM_CONFIG_H
#define THERMALSIM_CONFIG_H

#include <systemc.h>
#include <iostream>
#include <string>

#include "../../../common/DebugManager.h"
#include "../../../common/third_party/tinyxml2/tinyxml2.h"
#include "../../../common/Utils.h"

struct TemperatureSimConfig {

    // Temperature Scale
    std::string TemperatureScale;
    std::string pathToResources;

    void setPathToResources(std::string path)
    {
        pathToResources = path;
    }

    // Static Temperature Simulation parameters
    int StaticTemperatureDefaultValue;

    // Thermal Simulation parameters
    double ThermalSimPeriod;
    enum sc_time_unit ThermalSimUnit;
    std::string IceServerIp;
    unsigned int IceServerPort;
    unsigned int SimPeriodAdjustFactor;
    unsigned int NPowStableCyclesToIncreasePeriod;
    bool GenerateTemperatureMap;
    bool GeneratePowerMap;

    // Power related information
    std::string powerInfoFile;
    std::vector<float> powerInitialValues;
    std::vector<float> powerThresholds;

    void parsePowerInfoFile()
    {
        printDebugMessage("Power Info File: " + powerInfoFile);

        powerInfoFile = pathToResources
                        + "/configs/thermalsim/"
                        + powerInfoFile;

        // Load the XML file into memory and parse it
        tinyxml2::XMLDocument xml;
        loadXML(powerInfoFile, xml);
        tinyxml2::XMLElement *powInfoElem = xml.FirstChildElement("powerInfo");

        if (powInfoElem == NULL) {
            // Invalid file
            std::string errormsg = "Invalid Power Info File " + powerInfoFile;
            printDebugMessage(errormsg);
            SC_REPORT_FATAL("Temperature Sim Config", errormsg.c_str());
        }

        for (tinyxml2::XMLElement *e = powInfoElem->FirstChildElement(); e != NULL;
                e = e->NextSiblingElement()) {

            // Load initial power values for all devices
            std::string init_pow_str = e->Attribute("init_pow");
            float pow = std::stof(init_pow_str);
            powerInitialValues.push_back(pow);

            // Load power thresholds for all devices (changes in power dissipation that exceed the threshods will make the thermal simulation to be executed more often)
            std::string thr_str = e->Attribute("threshold");
            float thr = std::stof(thr_str);
            powerThresholds.push_back(thr);
        }

        showTemperatureSimConfig();
    }

    void showTemperatureSimConfig()
    {
        int i = 0;
        for (auto e : powerInitialValues) {
            printDebugMessage("powerInitialValues[" + std::to_string(
                                  i++) + "]: " + std::to_string(e));
        }
        i = 0;
        for (auto e : powerThresholds) {
            printDebugMessage("powerThreshold[" + std::to_string(i++) + "]: " +
                              std::to_string(e));
        }
    }

    void printDebugMessage(std::string message)
    {
        DebugManager::getInstance().printDebugMessage("Temperature Sim Config",
                                                      message);
    }
};

#endif /* THERMALSIM_CONFIG_H */

