/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * 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.
 */

// Autogenerated by dumpstate_hal_config.xsd

#define LOG_TAG "dumpstate.hal.configuration.V1_0"

#include <memory>

#include <libxml/parser.h>
#include <libxml/xinclude.h>

#include "config/dumpstate_hal_configuration_V1_0.h"

namespace dumpstate {
namespace hal {
namespace configuration {
namespace V1_0 {
template <class T>
constexpr void (*xmlDeleter)(T* t);
template <>
constexpr auto xmlDeleter<xmlDoc> = xmlFreeDoc;
template <>
auto xmlDeleter<xmlChar> = [](xmlChar* s) { xmlFree(s); };

template <class T>
constexpr auto make_xmlUnique(T* t) {
    auto deleter = [](T* t) { xmlDeleter<T>(t); };
    return std::unique_ptr<T, decltype(deleter)>{t, deleter};
}

static std::string getXmlAttribute(const xmlNode* cur, const char* attribute) {
    auto xmlValue = make_xmlUnique(xmlGetProp(cur, reinterpret_cast<const xmlChar*>(attribute)));
    if (xmlValue == nullptr) {
        return "";
    }
    std::string value(reinterpret_cast<const char*>(xmlValue.get()));
    return value;
}

std::optional<DumpstateHalConfiguration> readBuffer(const std::string& xml) {
    auto doc = make_xmlUnique(xmlParseMemory(xml.data(), xml.size()));
    if (doc == nullptr) {
        return std::nullopt;
    }
    xmlNodePtr child = xmlDocGetRootElement(doc.get());
    if (child == NULL) {
        return std::nullopt;
    }

    if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("dumpstateHalConfiguration"))) {
        DumpstateHalConfiguration value = DumpstateHalConfiguration::read(child);
        return value;
    }
    return std::nullopt;
}

std::optional<DumpstateHalConfiguration> readFile(const char* configFile) {
    auto doc = make_xmlUnique(xmlParseFile(configFile));
    if (doc == nullptr) {
        return std::nullopt;
    }
    xmlNodePtr child = xmlDocGetRootElement(doc.get());
    if (child == NULL) {
        return std::nullopt;
    }

    if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("dumpstateHalConfiguration"))) {
        DumpstateHalConfiguration value = DumpstateHalConfiguration::read(child);
        return value;
    }
    return std::nullopt;
}

Service::Service(std::string name, std::string command)
    : name_(std::move(name)), command_(std::move(command)) {}

const std::string& Service::getName() const {
    return name_;
}

bool Service::hasName() const {
    return true;
}

const std::string& Service::getCommand() const {
    return command_;
}

bool Service::hasCommand() const {
    return true;
}

Service Service::read(xmlNode* root) {
    std::string raw;
    raw = getXmlAttribute(root, "name");
    std::string name;
    if (raw != "") {
        std::string& value = raw;
        name = value;
    }
    raw = getXmlAttribute(root, "command");
    std::string command;
    if (raw != "") {
        std::string& value = raw;
        command = value;
    }
    Service instance(name, command);
    return instance;
}

Services::Services(std::vector<Service> service) : service_(std::move(service)) {}

const std::vector<Service>& Services::getService() const {
    return service_;
}

bool Services::hasService() const {
    return !(service_.empty());
}

const Service* Services::getFirstService() const {
    if (service_.empty()) {
        return nullptr;
    }
    return &service_[0];
}

Services Services::read(xmlNode* root) {
    std::string raw;
    std::vector<Service> service;
    for (xmlNode* child = root->xmlChildrenNode; child != nullptr; child = child->next) {
        if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("service"))) {
            Service value = Service::read(child);
            service.push_back(std::move(value));
        }
    }
    Services instance(service);
    return instance;
}

SystemLogs::SystemLogs(std::vector<Service> service) : service_(std::move(service)) {}

const std::vector<Service>& SystemLogs::getService() const {
    return service_;
}

bool SystemLogs::hasService() const {
    return !(service_.empty());
}

const Service* SystemLogs::getFirstService() const {
    if (service_.empty()) {
        return nullptr;
    }
    return &service_[0];
}

SystemLogs SystemLogs::read(xmlNode* root) {
    std::string raw;
    std::vector<Service> service;
    for (xmlNode* child = root->xmlChildrenNode; child != nullptr; child = child->next) {
        if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("service"))) {
            Service value = Service::read(child);
            service.push_back(std::move(value));
        }
    }
    SystemLogs instance(service);
    return instance;
}

DumpstateHalConfiguration::DumpstateHalConfiguration(std::vector<Services> services,
                                                     std::vector<SystemLogs> systemLogs,
                                                     float version)
    : services_(std::move(services)), systemLogs_(std::move(systemLogs)), version_(version) {}

const std::vector<Services>& DumpstateHalConfiguration::getServices() const {
    return services_;
}

bool DumpstateHalConfiguration::hasServices() const {
    return !(services_.empty());
}

const Services* DumpstateHalConfiguration::getFirstServices() const {
    if (services_.empty()) {
        return nullptr;
    }
    return &services_[0];
}

const std::vector<SystemLogs>& DumpstateHalConfiguration::getSystemLogs() const {
    return systemLogs_;
}

bool DumpstateHalConfiguration::hasSystemLogs() const {
    return !(systemLogs_.empty());
}

const SystemLogs* DumpstateHalConfiguration::getFirstSystemLogs() const {
    if (systemLogs_.empty()) {
        return nullptr;
    }
    return &systemLogs_[0];
}

const float& DumpstateHalConfiguration::getVersion() const {
    return version_;
}

bool DumpstateHalConfiguration::hasVersion() const {
    return true;
}

DumpstateHalConfiguration DumpstateHalConfiguration::read(xmlNode* root) {
    std::string raw;
    raw = getXmlAttribute(root, "version");
    float version = 0;
    if (raw != "") {
        float value = std::stof(raw);
        version = value;
    }
    std::vector<Services> services;
    std::vector<SystemLogs> systemLogs;
    for (xmlNode* child = root->xmlChildrenNode; child != nullptr; child = child->next) {
        if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("services"))) {
            Services value = Services::read(child);
            services.push_back(std::move(value));
        } else if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("systemLogs"))) {
            SystemLogs value = SystemLogs::read(child);
            systemLogs.push_back(std::move(value));
        }
    }
    DumpstateHalConfiguration instance(services, systemLogs, version);
    return instance;
}
}  // namespace V1_0
}  // namespace configuration
}  // namespace hal
}  // namespace dumpstate
