/**
 * 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.
 */

#include "pid/builder.hpp"

#include "conf.hpp"
#include "pid/controller.hpp"
#include "pid/fancontroller.hpp"
#include "pid/stepwisecontroller.hpp"
#include "pid/thermalcontroller.hpp"

#include <sdbusplus/bus.hpp>

#include <iostream>
#include <memory>
#include <unordered_map>

namespace pid_control
{

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

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

std::unordered_map<int64_t, std::unique_ptr<DbusPidZone>>
    buildZones(const std::map<int64_t, conf::PIDConf>& zonePids,
               std::map<int64_t, struct conf::ZoneConfig>& zoneConfigs,
               SensorManager& mgr, sdbusplus::bus::bus& modeControlBus)
{
    std::unordered_map<int64_t, std::unique_ptr<DbusPidZone>> zones;

    for (const 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);
        }

        const conf::PIDConf& pidConfig = zi.second;

        auto zone = std::make_unique<DbusPidZone>(
            zoneId, zoneConf->second.minThermalOutput,
            zoneConf->second.failsafePercent, mgr, modeControlBus,
            getControlPath(zi.first).c_str(), deferSignals);

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

        // For each PID create a Controller and a Sensor.
        for (const auto& pit : pidConfig)
        {
            std::vector<std::string> inputs;
            std::string name = pit.first;
            const struct conf::ControllerInfo* 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 (const auto& i : info->inputs)
                {
                    inputs.push_back(i);
                    zone->addFanInput(i);
                }

                auto pid = FanController::createFanPid(zone.get(), name, inputs,
                                                       info->pidInfo);
                zone->addFanPID(std::move(pid));
            }
            else if (isThermalType(info->type))
            {
                for (const auto& i : info->inputs)
                {
                    inputs.push_back(i);
                    zone->addThermalInput(i);
                }

                auto pid = ThermalController::createThermalPid(
                    zone.get(), name, inputs, info->setpoint, info->pidInfo,
                    getThermalType(info->type));

                zone->addThermalPID(std::move(pid));
            }
            else if (info->type == "stepwise")
            {
                for (const auto& i : info->inputs)
                {
                    inputs.push_back(i);
                    zone->addThermalInput(i);
                }
                auto stepwise = StepwiseController::createStepwiseController(
                    zone.get(), name, inputs, info->stepwiseInfo);
                zone->addThermalPID(std::move(stepwise));
            }

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

        zone->emit_object_added();
        zones[zoneId] = std::move(zone);
    }

    return zones;
}

} // namespace pid_control
