/**
 * Copyright © 2020 IBM 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_file_parser.hpp"

#include "config_file_parser_error.hpp"
#include "i2c_interface.hpp"
#include "pmbus_utils.hpp"

#include <exception>
#include <fstream>
#include <optional>
#include <utility>

using json = nlohmann::json;

namespace phosphor::power::regulators::config_file_parser
{

std::tuple<std::vector<std::unique_ptr<Rule>>,
           std::vector<std::unique_ptr<Chassis>>>
    parse(const std::filesystem::path& pathName)
{
    try
    {
        // Use standard JSON parser to create tree of JSON elements
        std::ifstream file{pathName};
        json rootElement = json::parse(file);

        // Parse tree of JSON elements and return corresponding C++ objects
        return internal::parseRoot(rootElement);
    }
    catch (const std::exception& e)
    {
        throw ConfigFileParserError{pathName, e.what()};
    }
}

namespace internal
{

std::unique_ptr<Action> parseAction(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Optional comments property; value not stored
    if (element.contains("comments"))
    {
        ++propertyCount;
    }

    // Required action type property; there must be exactly one specified
    std::unique_ptr<Action> action{};
    if (element.contains("and"))
    {
        action = parseAnd(element["and"]);
        ++propertyCount;
    }
    else if (element.contains("compare_presence"))
    {
        action = parseComparePresence(element["compare_presence"]);
        ++propertyCount;
    }
    else if (element.contains("compare_vpd"))
    {
        action = parseCompareVPD(element["compare_vpd"]);
        ++propertyCount;
    }
    else if (element.contains("i2c_compare_bit"))
    {
        action = parseI2CCompareBit(element["i2c_compare_bit"]);
        ++propertyCount;
    }
    else if (element.contains("i2c_compare_byte"))
    {
        action = parseI2CCompareByte(element["i2c_compare_byte"]);
        ++propertyCount;
    }
    else if (element.contains("i2c_compare_bytes"))
    {
        action = parseI2CCompareBytes(element["i2c_compare_bytes"]);
        ++propertyCount;
    }
    else if (element.contains("i2c_write_bit"))
    {
        action = parseI2CWriteBit(element["i2c_write_bit"]);
        ++propertyCount;
    }
    else if (element.contains("i2c_write_byte"))
    {
        action = parseI2CWriteByte(element["i2c_write_byte"]);
        ++propertyCount;
    }
    else if (element.contains("i2c_write_bytes"))
    {
        action = parseI2CWriteBytes(element["i2c_write_bytes"]);
        ++propertyCount;
    }
    else if (element.contains("if"))
    {
        action = parseIf(element["if"]);
        ++propertyCount;
    }
    else if (element.contains("not"))
    {
        action = parseNot(element["not"]);
        ++propertyCount;
    }
    else if (element.contains("or"))
    {
        action = parseOr(element["or"]);
        ++propertyCount;
    }
    else if (element.contains("pmbus_read_sensor"))
    {
        action = parsePMBusReadSensor(element["pmbus_read_sensor"]);
        ++propertyCount;
    }
    else if (element.contains("pmbus_write_vout_command"))
    {
        action =
            parsePMBusWriteVoutCommand(element["pmbus_write_vout_command"]);
        ++propertyCount;
    }
    else if (element.contains("run_rule"))
    {
        action = parseRunRule(element["run_rule"]);
        ++propertyCount;
    }
    else if (element.contains("set_device"))
    {
        action = parseSetDevice(element["set_device"]);
        ++propertyCount;
    }
    else
    {
        throw std::invalid_argument{"Required action type property missing"};
    }

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return action;
}

std::vector<std::unique_ptr<Action>> parseActionArray(const json& element)
{
    verifyIsArray(element);
    std::vector<std::unique_ptr<Action>> actions;
    for (auto& actionElement : element)
    {
        actions.emplace_back(parseAction(actionElement));
    }
    return actions;
}

std::unique_ptr<AndAction> parseAnd(const json& element)
{
    verifyIsArray(element);

    // Verify if array size less than 2
    if (element.size() < 2)
    {
        throw std::invalid_argument{"Array must contain two or more actions"};
    }
    // Array of two or more actions
    std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);

    return std::make_unique<AndAction>(std::move(actions));
}

std::unique_ptr<Chassis> parseChassis(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Optional comments property; value not stored
    if (element.contains("comments"))
    {
        ++propertyCount;
    }

    // Required number property
    const json& numberElement = getRequiredProperty(element, "number");
    unsigned int number = parseUnsignedInteger(numberElement);
    if (number < 1)
    {
        throw std::invalid_argument{"Invalid chassis number: Must be > 0"};
    }
    ++propertyCount;

    // Optional inventory_path property.  Will be required in future.
    std::string inventoryPath{"/xyz/openbmc_project/inventory/system/chassis"};
    auto inventoryPathIt = element.find("inventory_path");
    if (inventoryPathIt != element.end())
    {
        inventoryPath = parseInventoryPath(*inventoryPathIt);
        ++propertyCount;
    }

    // Optional devices property
    std::vector<std::unique_ptr<Device>> devices{};
    auto devicesIt = element.find("devices");
    if (devicesIt != element.end())
    {
        devices = parseDeviceArray(*devicesIt);
        ++propertyCount;
    }

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return std::make_unique<Chassis>(number, inventoryPath, std::move(devices));
}

std::vector<std::unique_ptr<Chassis>> parseChassisArray(const json& element)
{
    verifyIsArray(element);
    std::vector<std::unique_ptr<Chassis>> chassis;
    for (auto& chassisElement : element)
    {
        chassis.emplace_back(parseChassis(chassisElement));
    }
    return chassis;
}

std::unique_ptr<ComparePresenceAction> parseComparePresence(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Required fru property
    const json& fruElement = getRequiredProperty(element, "fru");
    std::string fru = parseInventoryPath(fruElement);
    ++propertyCount;

    // Required value property
    const json& valueElement = getRequiredProperty(element, "value");
    bool value = parseBoolean(valueElement);
    ++propertyCount;

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return std::make_unique<ComparePresenceAction>(fru, value);
}

std::unique_ptr<CompareVPDAction> parseCompareVPD(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Required fru property
    const json& fruElement = getRequiredProperty(element, "fru");
    std::string fru = parseInventoryPath(fruElement);
    ++propertyCount;

    // Required keyword property
    const json& keywordElement = getRequiredProperty(element, "keyword");
    std::string keyword = parseString(keywordElement);
    ++propertyCount;

    // Required value property
    const json& valueElement = getRequiredProperty(element, "value");
    std::string value = parseString(valueElement);
    ++propertyCount;

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return std::make_unique<CompareVPDAction>(fru, keyword, value);
}

std::unique_ptr<Configuration> parseConfiguration(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Optional comments property; value not stored
    if (element.contains("comments"))
    {
        ++propertyCount;
    }

    // Optional volts property
    std::optional<double> volts{};
    auto voltsIt = element.find("volts");
    if (voltsIt != element.end())
    {
        volts = parseDouble(*voltsIt);
        ++propertyCount;
    }

    // Required rule_id or actions property
    std::vector<std::unique_ptr<Action>> actions{};
    actions = parseRuleIDOrActionsProperty(element);
    ++propertyCount;

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return std::make_unique<Configuration>(volts, std::move(actions));
}

std::unique_ptr<Device> parseDevice(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Optional comments property; value not stored
    if (element.contains("comments"))
    {
        ++propertyCount;
    }

    // Required id property
    const json& idElement = getRequiredProperty(element, "id");
    std::string id = parseString(idElement);
    ++propertyCount;

    // Required is_regulator property
    const json& isRegulatorElement =
        getRequiredProperty(element, "is_regulator");
    bool isRegulator = parseBoolean(isRegulatorElement);
    ++propertyCount;

    // Required fru property
    const json& fruElement = getRequiredProperty(element, "fru");
    std::string fru = parseInventoryPath(fruElement);
    ++propertyCount;

    // Required i2c_interface property
    const json& i2cInterfaceElement =
        getRequiredProperty(element, "i2c_interface");
    std::unique_ptr<i2c::I2CInterface> i2cInterface =
        parseI2CInterface(i2cInterfaceElement);
    ++propertyCount;

    // Optional presence_detection property
    std::unique_ptr<PresenceDetection> presenceDetection{};
    auto presenceDetectionIt = element.find("presence_detection");
    if (presenceDetectionIt != element.end())
    {
        presenceDetection = parsePresenceDetection(*presenceDetectionIt);
        ++propertyCount;
    }

    // Optional configuration property
    std::unique_ptr<Configuration> configuration{};
    auto configurationIt = element.find("configuration");
    if (configurationIt != element.end())
    {
        configuration = parseConfiguration(*configurationIt);
        ++propertyCount;
    }

    // Optional rails property
    std::vector<std::unique_ptr<Rail>> rails{};
    auto railsIt = element.find("rails");
    if (railsIt != element.end())
    {
        if (!isRegulator)
        {
            throw std::invalid_argument{
                "Invalid rails property when is_regulator is false"};
        }
        rails = parseRailArray(*railsIt);
        ++propertyCount;
    }

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return std::make_unique<Device>(id, isRegulator, fru,
                                    std::move(i2cInterface),
                                    std::move(presenceDetection),
                                    std::move(configuration), std::move(rails));
}

std::vector<std::unique_ptr<Device>> parseDeviceArray(const json& element)
{
    verifyIsArray(element);
    std::vector<std::unique_ptr<Device>> devices;
    for (auto& deviceElement : element)
    {
        devices.emplace_back(parseDevice(deviceElement));
    }
    return devices;
}

std::vector<uint8_t> parseHexByteArray(const json& element)
{
    verifyIsArray(element);
    std::vector<uint8_t> values;
    for (auto& valueElement : element)
    {
        values.emplace_back(parseHexByte(valueElement));
    }
    return values;
}

std::unique_ptr<I2CCompareBitAction> parseI2CCompareBit(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Required register property
    const json& regElement = getRequiredProperty(element, "register");
    uint8_t reg = parseHexByte(regElement);
    ++propertyCount;

    // Required position property
    const json& positionElement = getRequiredProperty(element, "position");
    uint8_t position = parseBitPosition(positionElement);
    ++propertyCount;

    // Required value property
    const json& valueElement = getRequiredProperty(element, "value");
    uint8_t value = parseBitValue(valueElement);
    ++propertyCount;

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return std::make_unique<I2CCompareBitAction>(reg, position, value);
}

std::unique_ptr<I2CCompareByteAction> parseI2CCompareByte(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Required register property
    const json& regElement = getRequiredProperty(element, "register");
    uint8_t reg = parseHexByte(regElement);
    ++propertyCount;

    // Required value property
    const json& valueElement = getRequiredProperty(element, "value");
    uint8_t value = parseHexByte(valueElement);
    ++propertyCount;

    // Optional mask property
    uint8_t mask = 0xff;
    auto maskIt = element.find("mask");
    if (maskIt != element.end())
    {
        mask = parseHexByte(*maskIt);
        ++propertyCount;
    }

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return std::make_unique<I2CCompareByteAction>(reg, value, mask);
}

std::unique_ptr<I2CCompareBytesAction> parseI2CCompareBytes(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Required register property
    const json& regElement = getRequiredProperty(element, "register");
    uint8_t reg = parseHexByte(regElement);
    ++propertyCount;

    // Required values property
    const json& valueElement = getRequiredProperty(element, "values");
    std::vector<uint8_t> values = parseHexByteArray(valueElement);
    ++propertyCount;

    // Optional masks property
    std::vector<uint8_t> masks{};
    auto masksIt = element.find("masks");
    if (masksIt != element.end())
    {
        masks = parseHexByteArray(*masksIt);
        ++propertyCount;
    }

    // Verify masks array (if specified) was same size as values array
    if ((!masks.empty()) && (masks.size() != values.size()))
    {
        throw std::invalid_argument{"Invalid number of elements in masks"};
    }

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    if (masks.empty())
    {
        return std::make_unique<I2CCompareBytesAction>(reg, values);
    }
    return std::make_unique<I2CCompareBytesAction>(reg, values, masks);
}

std::unique_ptr<i2c::I2CInterface> parseI2CInterface(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Required bus property
    const json& busElement = getRequiredProperty(element, "bus");
    uint8_t bus = parseUint8(busElement);
    ++propertyCount;

    // Required address property
    const json& addressElement = getRequiredProperty(element, "address");
    uint8_t address = parseHexByte(addressElement);
    ++propertyCount;

    verifyPropertyCount(element, propertyCount);
    return i2c::create(bus, address, i2c::I2CInterface::InitialState::CLOSED);
}

std::unique_ptr<I2CWriteBitAction> parseI2CWriteBit(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Required register property
    const json& regElement = getRequiredProperty(element, "register");
    uint8_t reg = parseHexByte(regElement);
    ++propertyCount;

    // Required position property
    const json& positionElement = getRequiredProperty(element, "position");
    uint8_t position = parseBitPosition(positionElement);
    ++propertyCount;

    // Required value property
    const json& valueElement = getRequiredProperty(element, "value");
    uint8_t value = parseBitValue(valueElement);
    ++propertyCount;

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return std::make_unique<I2CWriteBitAction>(reg, position, value);
}

std::unique_ptr<I2CWriteByteAction> parseI2CWriteByte(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Required register property
    const json& regElement = getRequiredProperty(element, "register");
    uint8_t reg = parseHexByte(regElement);
    ++propertyCount;

    // Required value property
    const json& valueElement = getRequiredProperty(element, "value");
    uint8_t value = parseHexByte(valueElement);
    ++propertyCount;

    // Optional mask property
    uint8_t mask = 0xff;
    auto maskIt = element.find("mask");
    if (maskIt != element.end())
    {
        mask = parseHexByte(*maskIt);
        ++propertyCount;
    }

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return std::make_unique<I2CWriteByteAction>(reg, value, mask);
}

std::unique_ptr<I2CWriteBytesAction> parseI2CWriteBytes(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Required register property
    const json& regElement = getRequiredProperty(element, "register");
    uint8_t reg = parseHexByte(regElement);
    ++propertyCount;

    // Required values property
    const json& valueElement = getRequiredProperty(element, "values");
    std::vector<uint8_t> values = parseHexByteArray(valueElement);
    ++propertyCount;

    // Optional masks property
    std::vector<uint8_t> masks{};
    auto masksIt = element.find("masks");
    if (masksIt != element.end())
    {
        masks = parseHexByteArray(*masksIt);
        ++propertyCount;
    }

    // Verify masks array (if specified) was same size as values array
    if ((!masks.empty()) && (masks.size() != values.size()))
    {
        throw std::invalid_argument{"Invalid number of elements in masks"};
    }

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    if (masks.empty())
    {
        return std::make_unique<I2CWriteBytesAction>(reg, values);
    }
    return std::make_unique<I2CWriteBytesAction>(reg, values, masks);
}

std::unique_ptr<IfAction> parseIf(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Required condition property
    const json& conditionElement = getRequiredProperty(element, "condition");
    std::unique_ptr<Action> conditionAction = parseAction(conditionElement);
    ++propertyCount;

    // Required then property
    const json& thenElement = getRequiredProperty(element, "then");
    std::vector<std::unique_ptr<Action>> thenActions =
        parseActionArray(thenElement);
    ++propertyCount;

    // Optional else property
    std::vector<std::unique_ptr<Action>> elseActions{};
    auto elseIt = element.find("else");
    if (elseIt != element.end())
    {
        elseActions = parseActionArray(*elseIt);
        ++propertyCount;
    }

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return std::make_unique<IfAction>(std::move(conditionAction),
                                      std::move(thenActions),
                                      std::move(elseActions));
}

std::string parseInventoryPath(const json& element)
{
    std::string inventoryPath = parseString(element);
    std::string absPath = "/xyz/openbmc_project/inventory";
    if (inventoryPath.front() != '/')
    {
        absPath += '/';
    }
    absPath += inventoryPath;
    return absPath;
}

std::unique_ptr<NotAction> parseNot(const json& element)
{
    // Required action to execute
    std::unique_ptr<Action> action = parseAction(element);

    return std::make_unique<NotAction>(std::move(action));
}

std::unique_ptr<OrAction> parseOr(const json& element)
{
    verifyIsArray(element);

    // Verify if array size less than 2
    if (element.size() < 2)
    {
        throw std::invalid_argument{"Array must contain two or more actions"};
    }
    // Array of two or more actions
    std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);

    return std::make_unique<OrAction>(std::move(actions));
}

std::unique_ptr<PMBusReadSensorAction> parsePMBusReadSensor(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Required type property
    const json& typeElement = getRequiredProperty(element, "type");
    SensorType type = parseSensorType(typeElement);
    ++propertyCount;

    // Required command property
    const json& commandElement = getRequiredProperty(element, "command");
    uint8_t command = parseHexByte(commandElement);
    ++propertyCount;

    // Required format property
    const json& formatElement = getRequiredProperty(element, "format");
    pmbus_utils::SensorDataFormat format = parseSensorDataFormat(formatElement);
    ++propertyCount;

    // Optional exponent property
    std::optional<int8_t> exponent{};
    auto exponentIt = element.find("exponent");
    if (exponentIt != element.end())
    {
        exponent = parseInt8(*exponentIt);
        ++propertyCount;
    }

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return std::make_unique<PMBusReadSensorAction>(type, command, format,
                                                   exponent);
}

std::unique_ptr<PMBusWriteVoutCommandAction>
    parsePMBusWriteVoutCommand(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Optional volts property
    std::optional<double> volts{};
    auto voltsIt = element.find("volts");
    if (voltsIt != element.end())
    {
        volts = parseDouble(*voltsIt);
        ++propertyCount;
    }

    // Required format property
    const json& formatElement = getRequiredProperty(element, "format");
    std::string formatString = parseString(formatElement);
    if (formatString != "linear")
    {
        throw std::invalid_argument{"Invalid format value: " + formatString};
    }
    pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear;
    ++propertyCount;

    // Optional exponent property
    std::optional<int8_t> exponent{};
    auto exponentIt = element.find("exponent");
    if (exponentIt != element.end())
    {
        exponent = parseInt8(*exponentIt);
        ++propertyCount;
    }

    // Optional is_verified property
    bool isVerified = false;
    auto isVerifiedIt = element.find("is_verified");
    if (isVerifiedIt != element.end())
    {
        isVerified = parseBoolean(*isVerifiedIt);
        ++propertyCount;
    }

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return std::make_unique<PMBusWriteVoutCommandAction>(volts, format,
                                                         exponent, isVerified);
}

std::unique_ptr<PresenceDetection> parsePresenceDetection(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Optional comments property; value not stored
    if (element.contains("comments"))
    {
        ++propertyCount;
    }

    // Required rule_id or actions property
    std::vector<std::unique_ptr<Action>> actions{};
    actions = parseRuleIDOrActionsProperty(element);
    ++propertyCount;

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return std::make_unique<PresenceDetection>(std::move(actions));
}

std::unique_ptr<Rail> parseRail(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Optional comments property; value not stored
    if (element.contains("comments"))
    {
        ++propertyCount;
    }

    // Required id property
    const json& idElement = getRequiredProperty(element, "id");
    std::string id = parseString(idElement);
    ++propertyCount;

    // Optional configuration property
    std::unique_ptr<Configuration> configuration{};
    auto configurationIt = element.find("configuration");
    if (configurationIt != element.end())
    {
        configuration = parseConfiguration(*configurationIt);
        ++propertyCount;
    }

    // Optional sensor_monitoring property
    std::unique_ptr<SensorMonitoring> sensorMonitoring{};
    auto sensorMonitoringIt = element.find("sensor_monitoring");
    if (sensorMonitoringIt != element.end())
    {
        sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt);
        ++propertyCount;
    }

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return std::make_unique<Rail>(id, std::move(configuration),
                                  std::move(sensorMonitoring));
}

std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
{
    verifyIsArray(element);
    std::vector<std::unique_ptr<Rail>> rails;
    for (auto& railElement : element)
    {
        rails.emplace_back(parseRail(railElement));
    }
    return rails;
}

std::tuple<std::vector<std::unique_ptr<Rule>>,
           std::vector<std::unique_ptr<Chassis>>>
    parseRoot(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Optional comments property; value not stored
    if (element.contains("comments"))
    {
        ++propertyCount;
    }

    // Optional rules property
    std::vector<std::unique_ptr<Rule>> rules{};
    auto rulesIt = element.find("rules");
    if (rulesIt != element.end())
    {
        rules = parseRuleArray(*rulesIt);
        ++propertyCount;
    }

    // Required chassis property
    const json& chassisElement = getRequiredProperty(element, "chassis");
    std::vector<std::unique_ptr<Chassis>> chassis =
        parseChassisArray(chassisElement);
    ++propertyCount;

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return std::make_tuple(std::move(rules), std::move(chassis));
}

std::unique_ptr<Rule> parseRule(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Optional comments property; value not stored
    if (element.contains("comments"))
    {
        ++propertyCount;
    }

    // Required id property
    const json& idElement = getRequiredProperty(element, "id");
    std::string id = parseString(idElement);
    ++propertyCount;

    // Required actions property
    const json& actionsElement = getRequiredProperty(element, "actions");
    std::vector<std::unique_ptr<Action>> actions =
        parseActionArray(actionsElement);
    ++propertyCount;

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return std::make_unique<Rule>(id, std::move(actions));
}

std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element)
{
    verifyIsArray(element);
    std::vector<std::unique_ptr<Rule>> rules;
    for (auto& ruleElement : element)
    {
        rules.emplace_back(parseRule(ruleElement));
    }
    return rules;
}

std::vector<std::unique_ptr<Action>>
    parseRuleIDOrActionsProperty(const json& element)
{
    verifyIsObject(element);
    // Required rule_id or actions property
    std::vector<std::unique_ptr<Action>> actions{};
    auto ruleIDIt = element.find("rule_id");
    auto actionsIt = element.find("actions");
    if ((actionsIt == element.end()) && (ruleIDIt != element.end()))
    {
        std::string ruleID = parseString(*ruleIDIt);
        actions.emplace_back(std::make_unique<RunRuleAction>(ruleID));
    }
    else if ((actionsIt != element.end()) && (ruleIDIt == element.end()))
    {
        actions = parseActionArray(*actionsIt);
    }
    else
    {
        throw std::invalid_argument{"Invalid property combination: Must "
                                    "contain either rule_id or actions"};
    }

    return actions;
}

std::unique_ptr<RunRuleAction> parseRunRule(const json& element)
{
    // String ruleID
    std::string ruleID = parseString(element);

    return std::make_unique<RunRuleAction>(ruleID);
}

pmbus_utils::SensorDataFormat parseSensorDataFormat(const json& element)
{
    if (!element.is_string())
    {
        throw std::invalid_argument{"Element is not a string"};
    }
    std::string value = element.get<std::string>();
    pmbus_utils::SensorDataFormat format{};

    if (value == "linear_11")
    {
        format = pmbus_utils::SensorDataFormat::linear_11;
    }
    else if (value == "linear_16")
    {
        format = pmbus_utils::SensorDataFormat::linear_16;
    }
    else
    {
        throw std::invalid_argument{"Element is not a sensor data format"};
    }

    return format;
}

std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element)
{
    verifyIsObject(element);
    unsigned int propertyCount{0};

    // Optional comments property; value not stored
    if (element.contains("comments"))
    {
        ++propertyCount;
    }

    // Required rule_id or actions property
    std::vector<std::unique_ptr<Action>> actions{};
    actions = parseRuleIDOrActionsProperty(element);
    ++propertyCount;

    // Verify no invalid properties exist
    verifyPropertyCount(element, propertyCount);

    return std::make_unique<SensorMonitoring>(std::move(actions));
}

SensorType parseSensorType(const json& element)
{
    if (!element.is_string())
    {
        throw std::invalid_argument{"Element is not a string"};
    }
    std::string value = element.get<std::string>();
    SensorType type{};

    if (value == "iout")
    {
        type = SensorType::iout;
    }
    else if (value == "iout_peak")
    {
        type = SensorType::iout_peak;
    }
    else if (value == "iout_valley")
    {
        type = SensorType::iout_valley;
    }
    else if (value == "pout")
    {
        type = SensorType::pout;
    }
    else if (value == "temperature")
    {
        type = SensorType::temperature;
    }
    else if (value == "temperature_peak")
    {
        type = SensorType::temperature_peak;
    }
    else if (value == "vout")
    {
        type = SensorType::vout;
    }
    else if (value == "vout_peak")
    {
        type = SensorType::vout_peak;
    }
    else if (value == "vout_valley")
    {
        type = SensorType::vout_valley;
    }
    else
    {
        throw std::invalid_argument{"Element is not a sensor type"};
    }

    return type;
}

std::unique_ptr<SetDeviceAction> parseSetDevice(const json& element)
{
    // String deviceID
    std::string deviceID = parseString(element);

    return std::make_unique<SetDeviceAction>(deviceID);
}

pmbus_utils::VoutDataFormat parseVoutDataFormat(const json& element)
{
    if (!element.is_string())
    {
        throw std::invalid_argument{"Element is not a string"};
    }
    std::string value = element.get<std::string>();
    pmbus_utils::VoutDataFormat format{};

    if (value == "linear")
    {
        format = pmbus_utils::VoutDataFormat::linear;
    }
    else if (value == "vid")
    {
        format = pmbus_utils::VoutDataFormat::vid;
    }
    else if (value == "direct")
    {
        format = pmbus_utils::VoutDataFormat::direct;
    }
    else if (value == "ieee")
    {
        format = pmbus_utils::VoutDataFormat::ieee;
    }
    else
    {
        throw std::invalid_argument{"Element is not a vout data format"};
    }

    return format;
}

} // namespace internal

} // namespace phosphor::power::regulators::config_file_parser
