/*
// Copyright (c) 2018 Intel Corporation
//
// 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 "config.h"

#include "button_config.hpp"

#include <error.h>
#include <fcntl.h>
#include <unistd.h>

#include <gpioplus/utility/aspeed.hpp>
#include <nlohmann/json.hpp>
#include <phosphor-logging/lg2.hpp>

#include <filesystem>
#include <fstream>

const std::string gpioDev = "/sys/class/gpio";
namespace fs = std::filesystem;
std::unordered_map<GpioPolarity, GPIOBufferValue> GpioValueMap = {
    {GpioPolarity::activeLow, {'0', '1'}},
    {GpioPolarity::activeHigh, {'1', '0'}}};

void setGpioState(int fd, GpioPolarity polarity, GpioState state)
{
    char writeBuffer;

    if (state == GpioState::assert)
    {
        writeBuffer = GpioValueMap[polarity].assert;
    }
    else
    {
        writeBuffer = GpioValueMap[polarity].deassert;
    }

    auto result = ::write(fd, &writeBuffer, sizeof(writeBuffer));
    if (result < 0)
    {
        lg2::error("GPIO write error {GPIOFD} : {ERRORNO}", "GPIOFD", fd,
                   "ERRORNO", errno);
    }
    return;
}
GpioState getGpioState(int fd, GpioPolarity polarity)
{
    int result = -1;
    char readBuffer = '0';

    result = ::lseek(fd, 0, SEEK_SET);

    if (result < 0)
    {
        lg2::error("GPIO lseek error {GPIOFD}: {ERROR}", "GPIOFD", fd, "ERROR",
                   errno);
        return GpioState::invalid;
    }

    result = ::read(fd, &readBuffer, sizeof(readBuffer));
    if (result < 0)
    {
        lg2::error("GPIO read error {GPIOFD}: {ERRORNO}", "GPIOFD", fd,
                   "ERRORNO", errno);
        throw std::runtime_error("GPIO read failed");
    }
    // read the gpio state for the io event received
    GpioState gpioState = (readBuffer == GpioValueMap[polarity].assert)
                              ? (GpioState::assert)
                              : (GpioState::deassert);
    return gpioState;
}

uint32_t getGpioBase()
{
    // Look for a /sys/class/gpio/gpiochip*/label file
    // with a value of GPIO_BASE_LABEL_NAME.  Then read
    // the base value from the 'base' file in that directory.
#ifdef LOOKUP_GPIO_BASE
    for (auto& f : fs::directory_iterator(gpioDev))
    {
        std::string path{f.path()};
        if (path.find("gpiochip") == std::string::npos)
        {
            continue;
        }

        std::ifstream labelStream{path + "/label"};
        std::string label;
        labelStream >> label;

        if (label == GPIO_BASE_LABEL_NAME)
        {
            uint32_t base;
            std::ifstream baseStream{path + "/base"};
            baseStream >> base;
            return base;
        }
    }

    lg2::error("Could not find GPIO base");
    throw std::runtime_error("Could not find GPIO base!");
#else
    return 0;
#endif
}

uint32_t getGpioNum(const std::string& gpioPin)
{
    // gpioplus promises that they will figure out how to easily
    // support multiple BMC vendors when the time comes.
    auto offset = gpioplus::utility::aspeed::nameToOffset(gpioPin);

    return getGpioBase() + offset;
}

int configGroupGpio(ButtonConfig& buttonIFConfig)
{
    int result = 0;
    // iterate the list of gpios from the button interface config
    // and initialize them
    for (auto& gpioCfg : buttonIFConfig.gpios)
    {
        result = configGpio(gpioCfg, buttonIFConfig);
        if (result < 0)
        {
            lg2::error("{NAME}: Error configuring gpio-{NUM}: {RESULT}", "NAME",
                       buttonIFConfig.formFactorName, "NUM", gpioCfg.number,
                       "RESULT", result);

            break;
        }
    }

    return result;
}

int configGpio(GpioInfo& gpioConfig, ButtonConfig& buttonIFConfig)
{
    auto gpioNum = gpioConfig.number;
    auto gpioDirection = gpioConfig.direction;

    std::string devPath{gpioDev};

    std::fstream stream;

    stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);

    devPath += "/gpio" + std::to_string(gpioNum) + "/value";

    fs::path fullPath(devPath);

    if (fs::exists(fullPath))
    {
        lg2::info("GPIO exported: {PATH}", "PATH", devPath);
    }
    else
    {
        devPath = gpioDev + "/export";

        stream.open(devPath, std::fstream::out);
        try
        {
            stream << gpioNum;
            stream.close();
        }

        catch (const std::exception& e)
        {
            lg2::error("{NUM} error in writing {PATH}: {ERROR}", "NUM", gpioNum,
                       "PATH", devPath, "ERROR", e);
            return -1;
        }
    }

    if (gpioDirection == "out")
    {
        devPath = gpioDev + "/gpio" + std::to_string(gpioNum) + "/value";

        uint32_t currentValue;

        stream.open(devPath, std::fstream::in);
        try
        {
            stream >> currentValue;
            stream.close();
        }

        catch (const std::exception& e)
        {
            lg2::error("Error in reading {PATH}: {ERROR}", "PATH", devPath,
                       "ERROR", e);
            return -1;
        }

        const char* direction = currentValue ? "high" : "low";

        devPath.clear();
        devPath = gpioDev + "/gpio" + std::to_string(gpioNum) + "/direction";

        stream.open(devPath, std::fstream::out);
        try
        {
            stream << direction;
            stream.close();
        }

        catch (const std::exception& e)
        {
            lg2::error("Error in writing: {ERROR}", "ERROR", e);
            return -1;
        }
    }
    else if (gpioDirection == "in")
    {
        devPath = gpioDev + "/gpio" + std::to_string(gpioNum) + "/direction";

        stream.open(devPath, std::fstream::out);
        try
        {
            stream << gpioDirection;
            stream.close();
        }

        catch (const std::exception& e)
        {
            lg2::error("Error in writing: {ERROR}", "ERROR", e);
            return -1;
        }
    }
    else if ((gpioDirection == "both"))
    {
        devPath = gpioDev + "/gpio" + std::to_string(gpioNum) + "/direction";

        stream.open(devPath, std::fstream::out);
        try
        {
            // Before set gpio configure as an interrupt pin, need to set
            // direction as 'in' or edge can't set as 'rising', 'falling' and
            // 'both'
            const char* in_direction = "in";
            stream << in_direction;
            stream.close();
        }

        catch (const std::exception& e)
        {
            lg2::error("Error in writing: {ERROR}", "ERROR", e);
            return -1;
        }
        devPath.clear();

        // For gpio configured as ‘both’, it is an interrupt pin and trigged on
        // both rising and falling signals
        devPath = gpioDev + "/gpio" + std::to_string(gpioNum) + "/edge";

        stream.open(devPath, std::fstream::out);
        try
        {
            stream << gpioDirection;
            stream.close();
        }

        catch (const std::exception& e)
        {
            lg2::error("Error in writing: {ERROR}", "ERROR", e);
            return -1;
        }
    }

    devPath = gpioDev + "/gpio" + std::to_string(gpioNum) + "/value";

    auto fd = ::open(devPath.c_str(), O_RDWR | O_NONBLOCK);

    if (fd < 0)
    {
        lg2::error("Open {PATH} error: {ERROR}", "PATH", devPath, "ERROR",
                   errno);
        return -1;
    }

    gpioConfig.fd = fd;
    buttonIFConfig.fds.push_back(fd);

    return 0;
}
