/*
 * Copyright (c) 2011-2015, Intel Corporation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors
 * may be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "ConfigurableElement.h"
#include "MappingData.h"
#include "SyncerSet.h"
#include "ConfigurableDomain.h"
#include "ConfigurationAccessContext.h"
#include "ConfigurableElementAggregator.h"
#include "AreaConfiguration.h"
#include "Iterator.hpp"
#include "Utility.h"
#include "XmlParameterSerializingContext.h"
#include <assert.h>

#define base CElement

CConfigurableElement::CConfigurableElement(const std::string &strName) : base(strName)
{
}

bool CConfigurableElement::fromXml(const CXmlElement &xmlElement,
                                   CXmlSerializingContext &serializingContext)
{
    auto &context = static_cast<CXmlParameterSerializingContext &>(serializingContext);
    auto &accessContext = context.getAccessContext();

    if (accessContext.serializeSettings()) {
        // As serialization and deserialisation are handled through the *same* function
        // the (de)serialize object can not be const in `serializeXmlSettings` signature.
        // As a result a const_cast is unavoidable :(.
        // Fixme: split serializeXmlSettings in two functions (in and out) to avoid the `const_cast`
        return serializeXmlSettings(const_cast<CXmlElement &>(xmlElement),
                                    static_cast<CConfigurationAccessContext &>(accessContext));
    }
    return structureFromXml(xmlElement, serializingContext);
}

void CConfigurableElement::toXml(CXmlElement &xmlElement,
                                 CXmlSerializingContext &serializingContext) const
{
    auto &context = static_cast<CXmlParameterSerializingContext &>(serializingContext);
    auto &accessContext = context.getAccessContext();
    if (accessContext.serializeSettings()) {

        serializeXmlSettings(xmlElement, static_cast<CConfigurationAccessContext &>(accessContext));
    } else {

        structureToXml(xmlElement, serializingContext);
    }
}

// XML configuration settings parsing
bool CConfigurableElement::serializeXmlSettings(
    CXmlElement &xmlConfigurationSettingsElementContent,
    CConfigurationAccessContext &configurationAccessContext) const
{
    size_t uiNbChildren = getNbChildren();

    if (!configurationAccessContext.serializeOut()) {
        // Just do basic checks and propagate to children
        CXmlElement::CChildIterator it(xmlConfigurationSettingsElementContent);

        CXmlElement xmlChildConfigurableElementSettingsElement;

        // Propagate to children
        for (size_t index = 0; index < uiNbChildren; index++) {

            // Get child
            const CConfigurableElement *pChildConfigurableElement =
                static_cast<const CConfigurableElement *>(getChild(index));

            if (!it.next(xmlChildConfigurableElementSettingsElement)) {

                // Structure error
                configurationAccessContext.setError(
                    "Configuration settings parsing: missing child node " +
                    pChildConfigurableElement->getXmlElementName() + " (name:" +
                    pChildConfigurableElement->getName() + ") in " + getName());

                return false;
            }

            // Check element type matches in type
            if (xmlChildConfigurableElementSettingsElement.getType() !=
                pChildConfigurableElement->getXmlElementName()) {

                // "Component" tag has been renamed to "ParameterBlock", but retro-compatibility
                // shall be ensured.
                //
                // So checking if this case occurs, i.e. element name is "ParameterBlock"
                // but xml setting name is "Component".
                bool compatibilityCase =
                    (pChildConfigurableElement->getXmlElementName() == "ParameterBlock") &&
                    (xmlChildConfigurableElementSettingsElement.getType() == "Component");

                // Error if the compatibility case does not occur.
                if (!compatibilityCase) {

                    // Type error
                    configurationAccessContext.setError(
                        "Configuration settings parsing: Settings "
                        "for configurable element " +
                        pChildConfigurableElement->getQualifiedPath() +
                        " does not match expected type: " +
                        xmlChildConfigurableElementSettingsElement.getType() + " instead of " +
                        pChildConfigurableElement->getKind());
                    return false;
                }
            }

            // Check element type matches in name
            if (xmlChildConfigurableElementSettingsElement.getNameAttribute() !=
                pChildConfigurableElement->getName()) {

                // Name error
                configurationAccessContext.setError(
                    "Configuration settings parsing: Under configurable element " +
                    getQualifiedPath() + ", expected element name " +
                    pChildConfigurableElement->getName() + " but found " +
                    xmlChildConfigurableElementSettingsElement.getNameAttribute() + " instead");

                return false;
            }

            // Parse child configurable element's settings
            if (!pChildConfigurableElement->serializeXmlSettings(
                    xmlChildConfigurableElementSettingsElement, configurationAccessContext)) {

                return false;
            }
        }
        // There should remain no configurable element to parse
        if (it.next(xmlChildConfigurableElementSettingsElement)) {

            // Structure error
            configurationAccessContext.setError(
                "Configuration settings parsing: Unexpected xml element node " +
                xmlChildConfigurableElementSettingsElement.getType() + " in " + getQualifiedPath());

            return false;
        }
    } else {
        // Handle element name attribute
        xmlConfigurationSettingsElementContent.setNameAttribute(getName());

        // Propagate to children
        for (size_t index = 0; index < uiNbChildren; index++) {

            const CConfigurableElement *pChildConfigurableElement =
                static_cast<const CConfigurableElement *>(getChild(index));

            // Create corresponding child element
            CXmlElement xmlChildConfigurableElementSettingsElement;

            xmlConfigurationSettingsElementContent.createChild(
                xmlChildConfigurableElementSettingsElement,
                pChildConfigurableElement->getXmlElementName());

            // Propagate
            pChildConfigurableElement->serializeXmlSettings(
                xmlChildConfigurableElementSettingsElement, configurationAccessContext);
        }
    }
    // Done
    return true;
}

// AreaConfiguration creation
CAreaConfiguration *CConfigurableElement::createAreaConfiguration(
    const CSyncerSet *pSyncerSet) const
{
    return new CAreaConfiguration(this, pSyncerSet);
}

// Parameter access
bool CConfigurableElement::accessValue(CPathNavigator &pathNavigator, std::string &strValue,
                                       bool bSet,
                                       CParameterAccessContext &parameterAccessContext) const
{
    std::string *pStrChildName = pathNavigator.next();

    if (!pStrChildName) {

        parameterAccessContext.setError((bSet ? "Can't set " : "Can't get ") +
                                        pathNavigator.getCurrentPath() +
                                        " because it is not a parameter");

        return false;
    }

    const CConfigurableElement *pChild =
        static_cast<const CConfigurableElement *>(findChild(*pStrChildName));

    if (!pChild) {

        parameterAccessContext.setError("Path not found: " + pathNavigator.getCurrentPath());

        return false;
    }

    return pChild->accessValue(pathNavigator, strValue, bSet, parameterAccessContext);
}

// Whole element access
void CConfigurableElement::getSettingsAsBytes(std::vector<uint8_t> &bytes,
                                              CParameterAccessContext &parameterAccessContext) const
{
    bytes.resize(getFootPrint());

    parameterAccessContext.getParameterBlackboard()->readBytes(
        bytes, getOffset() - parameterAccessContext.getBaseOffset());
}

bool CConfigurableElement::setSettingsAsBytes(const std::vector<uint8_t> &bytes,
                                              CParameterAccessContext &parameterAccessContext) const
{
    CParameterBlackboard *pParameterBlackboard = parameterAccessContext.getParameterBlackboard();

    // Size
    size_t size = getFootPrint();

    // Check sizes match
    if (size != bytes.size()) {

        parameterAccessContext.setError(std::string("Wrong size: Expected: ") +
                                        std::to_string(size) + " Provided: " +
                                        std::to_string(bytes.size()));

        return false;
    }

    // Write bytes
    pParameterBlackboard->writeBytes(bytes, getOffset() - parameterAccessContext.getBaseOffset());

    if (not parameterAccessContext.getAutoSync()) {
        // Auto sync is not activated, sync will be defered until an explicit request
        return true;
    }

    CSyncerSet syncerSet;
    fillSyncerSet(syncerSet);
    core::Results res;
    if (not syncerSet.sync(*parameterAccessContext.getParameterBlackboard(), false, &res)) {

        parameterAccessContext.setError(utility::asString(res));
        return false;
    }
    return true;
}

std::list<const CConfigurableElement *> CConfigurableElement::getConfigurableElementContext() const
{
    std::list<const CConfigurableElement *> configurableElementPath;

    const CElement *element = this;
    while (element != nullptr and isOfConfigurableElementType(element)) {
        auto configurableElement = static_cast<const CConfigurableElement *>(element);

        configurableElementPath.push_back(configurableElement);
        element = element->getParent();
    }

    return configurableElementPath;
}

// Used for simulation and virtual subsystems
void CConfigurableElement::setDefaultValues(CParameterAccessContext &parameterAccessContext) const
{
    // Propagate to children
    size_t uiNbChildren = getNbChildren();

    for (size_t index = 0; index < uiNbChildren; index++) {

        const CConfigurableElement *pConfigurableElement =
            static_cast<const CConfigurableElement *>(getChild(index));

        pConfigurableElement->setDefaultValues(parameterAccessContext);
    }
}

// Element properties
void CConfigurableElement::showProperties(std::string &strResult) const
{
    base::showProperties(strResult);

    strResult += "Total size: " + getFootprintAsString() + "\n";
}

std::string CConfigurableElement::logValue(utility::ErrorContext &context) const
{
    return logValue(static_cast<CParameterAccessContext &>(context));
}

std::string CConfigurableElement::logValue(CParameterAccessContext & /*ctx*/) const
{
    // By default, an element does not have a value. Only leaf elements have
    // one. This method could be pure virtual but then, several derived classes
    // would need to implement it in order to simply return an empty string.
    return "";
}

// Offset
void CConfigurableElement::setOffset(size_t offset)
{
    // Assign offset locally
    _offset = offset;

    // Propagate to children
    size_t uiNbChildren = getNbChildren();

    for (size_t index = 0; index < uiNbChildren; index++) {

        CConfigurableElement *pConfigurableElement =
            static_cast<CConfigurableElement *>(getChild(index));

        pConfigurableElement->setOffset(offset);

        offset += pConfigurableElement->getFootPrint();
    }
}

size_t CConfigurableElement::getOffset() const
{
    return _offset;
}

// Memory
size_t CConfigurableElement::getFootPrint() const
{
    size_t uiSize = 0;
    size_t uiNbChildren = getNbChildren();

    for (size_t index = 0; index < uiNbChildren; index++) {

        const CConfigurableElement *pConfigurableElement =
            static_cast<const CConfigurableElement *>(getChild(index));

        uiSize += pConfigurableElement->getFootPrint();
    }

    return uiSize;
}

// Browse parent path to find syncer
ISyncer *CConfigurableElement::getSyncer() const
{
    // Check parent
    const CElement *pParent = getParent();

    if (isOfConfigurableElementType(pParent)) {

        return static_cast<const CConfigurableElement *>(pParent)->getSyncer();
    }
    return nullptr;
}

// Syncer set (me, ascendant or descendant ones)
void CConfigurableElement::fillSyncerSet(CSyncerSet &syncerSet) const
{
    //  Try me or ascendants
    ISyncer *pMineOrAscendantSyncer = getSyncer();

    if (pMineOrAscendantSyncer) {

        // Provide found syncer object
        syncerSet += pMineOrAscendantSyncer;

        // Done
        return;
    }
    // Fetch descendant ones
    fillSyncerSetFromDescendant(syncerSet);
}

// Syncer set (descendant)
void CConfigurableElement::fillSyncerSetFromDescendant(CSyncerSet &syncerSet) const
{
    // Dig
    size_t uiNbChildren = getNbChildren();

    for (size_t index = 0; index < uiNbChildren; index++) {

        const CConfigurableElement *pConfigurableElement =
            static_cast<const CConfigurableElement *>(getChild(index));

        pConfigurableElement->fillSyncerSetFromDescendant(syncerSet);
    }
}

// Configurable domain association
void CConfigurableElement::addAttachedConfigurableDomain(
    const CConfigurableDomain *pConfigurableDomain)
{
    _configurableDomainList.push_back(pConfigurableDomain);
}

void CConfigurableElement::removeAttachedConfigurableDomain(
    const CConfigurableDomain *pConfigurableDomain)
{
    _configurableDomainList.remove(pConfigurableDomain);
}

// Belonging domain
bool CConfigurableElement::belongsTo(const CConfigurableDomain *pConfigurableDomain) const
{
    if (containsConfigurableDomain(pConfigurableDomain)) {

        return true;
    }
    return belongsToDomainAscending(pConfigurableDomain);
}

// Belonging domains
void CConfigurableElement::getBelongingDomains(
    std::list<const CConfigurableDomain *> &configurableDomainList) const
{
    configurableDomainList.insert(configurableDomainList.end(), _configurableDomainList.begin(),
                                  _configurableDomainList.end());

    // Check parent
    const CElement *pParent = getParent();

    if (isOfConfigurableElementType(pParent)) {

        static_cast<const CConfigurableElement *>(pParent)->getBelongingDomains(
            configurableDomainList);
    }
}

void CConfigurableElement::listBelongingDomains(std::string &strResult, bool bVertical) const
{
    // Get belonging domain list
    std::list<const CConfigurableDomain *> configurableDomainList;

    getBelongingDomains(configurableDomainList);

    // Fill list
    listDomains(configurableDomainList, strResult, bVertical);
}

// Elements with no domains
void CConfigurableElement::listRogueElements(std::string &strResult) const
{
    // Get rogue element aggregate list (no associated domain)
    std::list<const CConfigurableElement *> rogueElementList;

    CConfigurableElementAggregator configurableElementAggregator(
        rogueElementList, &CConfigurableElement::hasNoDomainAssociated);

    configurableElementAggregator.aggegate(this);

    // Build list as std::string
    std::list<const CConfigurableElement *>::const_iterator it;

    for (it = rogueElementList.begin(); it != rogueElementList.end(); ++it) {

        const CConfigurableElement *pConfigurableElement = *it;

        strResult += pConfigurableElement->getPath() + "\n";
    }
}

bool CConfigurableElement::isRogue() const
{
    // Check not belonging to any domin from current level and towards ascendents
    if (getBelongingDomainCount() != 0) {

        return false;
    }

    // Get a list of elements (current + descendants) with no domains associated
    std::list<const CConfigurableElement *> rogueElementList;

    CConfigurableElementAggregator agregator(rogueElementList,
                                             &CConfigurableElement::hasNoDomainAssociated);

    agregator.aggegate(this);

    // Check only one element found which ought to be current one
    return (rogueElementList.size() == 1) && (rogueElementList.front() == this);
}

// Footprint as string
std::string CConfigurableElement::getFootprintAsString() const
{
    // Get size as string
    return std::to_string(getFootPrint()) + " byte(s)";
}

// Matching check for no domain association
bool CConfigurableElement::hasNoDomainAssociated() const
{
    return _configurableDomainList.empty();
}

// Matching check for no valid associated domains
bool CConfigurableElement::hasNoValidDomainAssociated() const
{
    if (_configurableDomainList.empty()) {

        // No domains associated
        return true;
    }

    ConfigurableDomainListConstIterator it;

    // Browse all configurable domains for validity checking
    for (it = _configurableDomainList.begin(); it != _configurableDomainList.end(); ++it) {

        const CConfigurableDomain *pConfigurableDomain = *it;

        if (pConfigurableDomain->isApplicableConfigurationValid(this)) {

            return false;
        }
    }

    return true;
}

// Owning domains
void CConfigurableElement::listAssociatedDomains(std::string &strResult, bool bVertical) const
{
    // Fill list
    listDomains(_configurableDomainList, strResult, bVertical);
}

size_t CConfigurableElement::getBelongingDomainCount() const
{
    // Get belonging domain list
    std::list<const CConfigurableDomain *> configurableDomainList;

    getBelongingDomains(configurableDomainList);

    return configurableDomainList.size();
}

void CConfigurableElement::listDomains(
    const std::list<const CConfigurableDomain *> &configurableDomainList, std::string &strResult,
    bool bVertical) const
{
    // Fill list
    ConfigurableDomainListConstIterator it;
    bool bFirst = true;

    // Browse all configurable domains for comparison
    for (it = configurableDomainList.begin(); it != configurableDomainList.end(); ++it) {

        const CConfigurableDomain *pConfigurableDomain = *it;

        if (!bVertical && !bFirst) {

            strResult += ", ";
        }

        strResult += pConfigurableDomain->getName();

        if (bVertical) {

            strResult += "\n";
        } else {

            bFirst = false;
        }
    }
}

bool CConfigurableElement::containsConfigurableDomain(
    const CConfigurableDomain *pConfigurableDomain) const
{
    ConfigurableDomainListConstIterator it;

    // Browse all configurable domains for comparison
    for (it = _configurableDomainList.begin(); it != _configurableDomainList.end(); ++it) {

        if (pConfigurableDomain == *it) {

            return true;
        }
    }
    return false;
}

// Belonging domain ascending search
bool CConfigurableElement::belongsToDomainAscending(
    const CConfigurableDomain *pConfigurableDomain) const
{
    // Check parent
    const CElement *pParent = getParent();

    if (isOfConfigurableElementType(pParent)) {

        return static_cast<const CConfigurableElement *>(pParent)->belongsTo(pConfigurableDomain);
    }
    return false;
}

// Belonging subsystem
const CSubsystem *CConfigurableElement::getBelongingSubsystem() const
{
    const CElement *pParent = getParent();

    // Stop at system class
    if (!pParent->getParent()) {

        return nullptr;
    }

    return static_cast<const CConfigurableElement *>(pParent)->getBelongingSubsystem();
}

// Check element is a parameter
bool CConfigurableElement::isParameter() const
{
    return false;
}

// Check parent is still of current type (by structure knowledge)
bool CConfigurableElement::isOfConfigurableElementType(const CElement *pParent) const
{
    assert(pParent);

    // Up to system class
    return !!pParent->getParent();
}
