/**
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* Configuration. */
#include "conf.hpp"

#include "zone.hpp"

#include <algorithm>
#include <chrono>
#include <cstring>
#include <fstream>
#include <iostream>
#include <libconfig.h++>
#include <memory>

#include "pid/controller.hpp"
#include "pid/fancontroller.hpp"
#include "pid/thermalcontroller.hpp"
#include "pid/ec/pid.hpp"


using tstamp = std::chrono::high_resolution_clock::time_point;
using namespace std::literals::chrono_literals;

static constexpr bool deferSignals = true;
static constexpr auto objectPath = "/xyz/openbmc_project/settings/fanctrl/zone";

float PIDZone::getMaxRPMRequest(void) const
{
    return _maximumRPMSetPt;
}

bool PIDZone::getManualMode(void) const
{
    return _manualMode;
}

void PIDZone::setManualMode(bool mode)
{
    _manualMode = mode;
}

bool PIDZone::getFailSafeMode(void) const
{
    // If any keys are present at least one sensor is in fail safe mode.
    return !_failSafeSensors.empty();
}

int64_t PIDZone::getZoneId(void) const
{
    return _zoneId;
}

void PIDZone::addRPMSetPoint(float setpoint)
{
    _RPMSetPoints.push_back(setpoint);
}

void PIDZone::clearRPMSetPoints(void)
{
    _RPMSetPoints.clear();
}

float PIDZone::getFailSafePercent(void) const
{
    return _failSafePercent;
}

float PIDZone::getMinThermalRpmSetPt(void) const
{
    return _minThermalRpmSetPt;
}

void PIDZone::addFanPID(std::unique_ptr<PIDController> pid)
{
    _fans.push_back(std::move(pid));
}

void PIDZone::addThermalPID(std::unique_ptr<PIDController> pid)
{
    _thermals.push_back(std::move(pid));
}

double PIDZone::getCachedValue(const std::string& name)
{
    return _cachedValuesByName.at(name);
}

void PIDZone::addFanInput(std::string fan)
{
    _fanInputs.push_back(fan);
}

void PIDZone::addThermalInput(std::string therm)
{
    _thermalInputs.push_back(therm);
}

void PIDZone::determineMaxRPMRequest(void)
{
    float max = 0;
    std::vector<float>::iterator result;

    if (_RPMSetPoints.size() > 0)
    {
        result = std::max_element(_RPMSetPoints.begin(), _RPMSetPoints.end());
        max = *result;
    }

    /*
     * If the maximum RPM set-point output is below the minimum RPM
     * set-point, set it to the minimum.
     */
    max = std::max(getMinThermalRpmSetPt(), max);

#ifdef __TUNING_LOGGING__
    /*
     * We received no set-points from thermal sensors.
     * This is a case experienced during tuning where they only specify
     * fan sensors and one large fan PID for all the fans.
     */
    static constexpr auto setpointpath = "/etc/thermal.d/set-point";
    try
    {
        int value;
        std::ifstream ifs;
        ifs.open(setpointpath);
        if (ifs.good()) {
            ifs >> value;
            max = value; // expecting RPM set-point, not pwm%
        }
    }
    catch (const std::exception& e)
    {
        /* This exception is uninteresting. */
        std::cerr << "Unable to read from '" << setpointpath << "'\n";
    }
#endif

    _maximumRPMSetPt = max;
    return;
}

#ifdef __TUNING_LOGGING__
void PIDZone::initializeLog(void)
{
    /* Print header for log file. */

    _log << "epoch_ms,setpt";

    for (auto& f : _fanInputs)
    {
        _log << "," << f;
    }
    _log << std::endl;

    return;
}

std::ofstream& PIDZone::getLogHandle(void)
{
    return _log;
}
#endif

/*
 * TODO(venture) This is effectively updating the cache and should check if the
 * values they're using to update it are new or old, or whatnot.  For instance,
 * if we haven't heard from the host in X time we need to detect this failure.
 *
 * I haven't decided if the Sensor should have a lastUpdated method or whether
 * that should be for the ReadInterface or etc...
 */

/**
 * We want the PID loop to run with values cached, so this will get all the
 * fan tachs for the loop.
 */
void PIDZone::updateFanTelemetry(void)
{
    /* TODO(venture): Should I just make _log point to /dev/null when logging
     * is disabled?  I think it's a waste to try and log things even if the
     * data is just being dropped though.
     */
#ifdef __TUNING_LOGGING__
    tstamp now = std::chrono::high_resolution_clock::now();
    _log << std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
    _log << "," << _maximumRPMSetPt;
#endif

    for (auto& f : _fanInputs)
    {
        auto& sensor = _mgr->getSensor(f);
        ReadReturn r = sensor->read();
        _cachedValuesByName[f] = r.value;

        /*
         * TODO(venture): We should check when these were last read.
         * However, these are the fans, so if I'm not getting updated values
         * for them... what should I do?
         */
#ifdef __TUNING_LOGGING__
        _log << "," << r.value;
#endif
    }

    return;
}

void PIDZone::updateSensors(void)
{
    using namespace std::chrono;
    /* margin and temp are stored as temp */
    tstamp now = high_resolution_clock::now();

    for (auto& t : _thermalInputs)
    {
        auto& sensor = _mgr->getSensor(t);
        ReadReturn r = sensor->read();
        int64_t timeout = sensor->GetTimeout();

        _cachedValuesByName[t] = r.value;
        tstamp then = r.updated;

        /* Only go into failsafe if the timeout is set for
         * the sensor.
         */
        if (timeout > 0)
        {
            auto duration = duration_cast<std::chrono::seconds>
                    (now - then).count();
            auto period = std::chrono::seconds(timeout).count();
            if (duration >= period)
            {
                //std::cerr << "Entering fail safe mode.\n";
                _failSafeSensors.insert(t);
            }
            else
            {
                // Check if it's in there: remove it.
                auto kt = _failSafeSensors.find(t);
                if (kt != _failSafeSensors.end())
                {
                    _failSafeSensors.erase(kt);
                }
            }
        }
    }

    return;
}

void PIDZone::initializeCache(void)
{
    for (auto& f : _fanInputs)
    {
        _cachedValuesByName[f] = 0;
    }

    for (auto& t : _thermalInputs)
    {
        _cachedValuesByName[t] = 0;

        // Start all sensors in fail-safe mode.
        _failSafeSensors.insert(t);
    }
}

void PIDZone::dumpCache(void)
{
    std::cerr << "Cache values now: \n";
    for (auto& k : _cachedValuesByName)
    {
        std::cerr << k.first << ": " << k.second << "\n";
    }
}

void PIDZone::process_fans(void)
{
    for (auto& p : _fans)
    {
        p->pid_process();
    }
}

void PIDZone::process_thermals(void)
{
    for (auto& p : _thermals)
    {
        p->pid_process();
    }
}

std::unique_ptr<Sensor>& PIDZone::getSensor(std::string name)
{
    return _mgr->getSensor(name);
}

bool PIDZone::manual(bool value)
{
    std::cerr << "manual: " << value << std::endl;
    setManualMode(value);
    return ModeObject::manual(value);
}

bool PIDZone::failSafe() const
{
    return getFailSafeMode();
}

static std::string GetControlPath(int64_t zone)
{
    return std::string(objectPath) + std::to_string(zone);
}

std::map<int64_t, std::shared_ptr<PIDZone>> BuildZones(
            std::map<int64_t, PIDConf>& ZonePids,
            std::map<int64_t, struct zone>& ZoneConfigs,
            std::shared_ptr<SensorManager> mgr,
            sdbusplus::bus::bus& ModeControlBus)
{
    std::map<int64_t, std::shared_ptr<PIDZone>> zones;

    for (auto& zi : ZonePids)
    {
        auto zoneId = static_cast<int64_t>(zi.first);
        /* The above shouldn't be necessary but is, and I am having trouble
         * locating my notes on why.  If I recall correctly it was casting it
         * down to a byte in at least some cases causing weird behaviors.
         */

        auto zoneConf = ZoneConfigs.find(zoneId);
        if (zoneConf == ZoneConfigs.end())
        {
            /* The Zone doesn't have a configuration, bail. */
            static constexpr auto err =
                "Bailing during load, missing Zone Configuration";
            std::cerr << err << std::endl;
            throw std::runtime_error(err);
        }

        PIDConf& PIDConfig = zi.second;

        auto zone = std::make_shared<PIDZone>(
                        zoneId,
                        zoneConf->second.minthermalrpm,
                        zoneConf->second.failsafepercent,
                        mgr,
                        ModeControlBus,
                        GetControlPath(zi.first).c_str(),
                        deferSignals);

        zones[zoneId] = zone;

        std::cerr << "Zone Id: " << zone->getZoneId() << "\n";

        // For each PID create a Controller and a Sensor.
        PIDConf::iterator pit = PIDConfig.begin();
        while (pit != PIDConfig.end())
        {
            std::vector<std::string> inputs;
            std::string name = pit->first;
            struct controller_info* info = &pit->second;

            std::cerr << "PID name: " << name << "\n";

            /*
             * TODO(venture): Need to check if input is known to the
             * SensorManager.
             */
            if (info->type == "fan")
            {
                for (auto i : info->inputs)
                {
                    inputs.push_back(i);
                    zone->addFanInput(i);
                }

                auto pid = FanController::CreateFanPid(
                               zone,
                               name,
                               inputs,
                               info->info);
                zone->addFanPID(std::move(pid));
            }
            else if (info->type == "temp" || info->type == "margin")
            {
                for (auto i : info->inputs)
                {
                    inputs.push_back(i);
                    zone->addThermalInput(i);
                }

                auto pid = ThermalController::CreateThermalPid(
                               zone,
                               name,
                               inputs,
                               info->setpoint,
                               info->info);
                zone->addThermalPID(std::move(pid));
            }

            std::cerr << "inputs: ";
            for (auto& i : inputs)
            {
                std::cerr << i << ", ";
            }
            std::cerr << "\n";

            ++pit;
        }

        zone->emit_object_added();
    }

    return zones;
}

std::map<int64_t, std::shared_ptr<PIDZone>> BuildZonesFromConfig(
            std::string& path,
            std::shared_ptr<SensorManager> mgr,
            sdbusplus::bus::bus& ModeControlBus)
{
    using namespace libconfig;
    // zone -> pids
    std::map<int64_t, PIDConf> pidConfig;
    // zone -> configs
    std::map<int64_t, struct zone> zoneConfig;

    std::cerr << "entered BuildZonesFromConfig\n";

    Config cfg;

    /* The load was modeled after the example source provided. */
    try
    {
        cfg.readFile(path.c_str());
    }
    catch (const FileIOException& fioex)
    {
        std::cerr << "I/O error while reading file: " << fioex.what() << std::endl;
        throw;
    }
    catch (const ParseException& pex)
    {
        std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
                  << " - " << pex.getError() << std::endl;
        throw;
    }

    try
    {
        const Setting& root = cfg.getRoot();
        const Setting& zones = root["zones"];
        int count = zones.getLength();

        /* For each zone. */
        for (int i = 0; i < count; ++i)
        {
            const Setting& zoneSettings = zones[i];

            int id;
            PIDConf thisZone;
            struct zone thisZoneConfig;

            zoneSettings.lookupValue("id", id);

            thisZoneConfig.minthermalrpm =
                    zoneSettings.lookup("minthermalrpm");
            thisZoneConfig.failsafepercent =
                    zoneSettings.lookup("failsafepercent");

            const Setting& pids = zoneSettings["pids"];
            int pidCount = pids.getLength();

            for (int j = 0; j < pidCount; ++j)
            {
                const Setting& pid = pids[j];

                std::string name;
                controller_info info;

                /*
                 * Mysteriously if you use lookupValue on these, and the type
                 * is float.  It won't work right.
                 *
                 * If the configuration file value doesn't look explicitly like
                 * a float it won't let you assign it to one.
                 */
                name = pid.lookup("name").c_str();
                info.type = pid.lookup("type").c_str();
                /* set-point is only required to be set for thermal. */
                /* TODO(venture): Verify this works optionally here. */
                info.setpoint = pid.lookup("set-point");
                info.info.ts = pid.lookup("pid.sampleperiod");
                info.info.p_c = pid.lookup("pid.p_coefficient");
                info.info.i_c = pid.lookup("pid.i_coefficient");
                info.info.ff_off = pid.lookup("pid.ff_off_coefficient");
                info.info.ff_gain = pid.lookup("pid.ff_gain_coefficient");
                info.info.i_lim.min = pid.lookup("pid.i_limit.min");
                info.info.i_lim.max = pid.lookup("pid.i_limit.max");
                info.info.out_lim.min = pid.lookup("pid.out_limit.min");
                info.info.out_lim.max = pid.lookup("pid.out_limit.max");
                info.info.slew_neg = pid.lookup("pid.slew_neg");
                info.info.slew_pos = pid.lookup("pid.slew_pos");

                std::cerr << "out_lim.min: " << info.info.out_lim.min << "\n";
                std::cerr << "out_lim.max: " << info.info.out_lim.max << "\n";

                const Setting& inputs = pid["inputs"];
                int icount = inputs.getLength();

                for (int z = 0; z < icount; ++z)
                {
                    std::string v;
                    v = pid["inputs"][z].c_str();
                    info.inputs.push_back(v);
                }

                thisZone[name] = info;
            }

            pidConfig[static_cast<int64_t>(id)] = thisZone;
            zoneConfig[static_cast<int64_t>(id)] = thisZoneConfig;
        }
    }
    catch (const SettingTypeException &setex)
    {
        std::cerr << "Setting '" << setex.getPath() << "' type exception!" << std::endl;
        throw;
    }
    catch (const SettingNotFoundException& snex)
    {
        std::cerr << "Setting '" << snex.getPath() << "' not found!" << std::endl;
        throw;
    }

    return BuildZones(pidConfig, zoneConfig, mgr, ModeControlBus);
}
