/*
 * Copyright (c) 2022, Technische Universität Kaiserslautern
 * 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.
 *
 * Authors:
 *    Iron Prando da Silva
 */

#include "StringMapper.h"

StringMapper::StringMapper(const QString& name) {
    mIDEnum = getIDEnum(name);
    mIDStr = name;
    mIsPool = mAuxIsPool(mIDEnum);

}

QString StringMapper::getIDStr(StringMapper::Identifier id) {
    static const std::map<StringMapper::Identifier, QString> enumToStr {
        {StringMapper::Identifier::CMD_BUS, "CMD_BUS"},
        {StringMapper::Identifier::RAS_BUS, "RAS_BUS"},
        {StringMapper::Identifier::CAS_BUS, "CAS_BUS"},
        {StringMapper::Identifier::NAW, "NAW"},
        {StringMapper::Identifier::FAW, "FAW"},
        {StringMapper::Identifier::_32AW, "32AW"},
        {StringMapper::Identifier::FAW_LOGICAL, "FAW_LOGICAL"},
        {StringMapper::Identifier::FAW_PHYSICAL, "FAW_PHYSICAL"},
        {StringMapper::Identifier::REFAB, "REFAB"},
        {StringMapper::Identifier::PREAB, "PREAB"},
        {StringMapper::Identifier::PDEP, "PDEP"},
        {StringMapper::Identifier::PDXP, "PDXP"},
        {StringMapper::Identifier::SREFEN, "SREFEN"},
        {StringMapper::Identifier::SREFEX, "SREFEX"},
        {StringMapper::Identifier::PDEA, "PDEA"},
        {StringMapper::Identifier::PDXA, "PDXA"},
        {StringMapper::Identifier::SRPDEN, "SRPDEN"},
        {StringMapper::Identifier::SRPDEX, "SRPDEX"},
        {StringMapper::Identifier::ACT, "ACT"},
        {StringMapper::Identifier::RD, "RD"},
        {StringMapper::Identifier::WR, "WR"},
        {StringMapper::Identifier::PREPB, "PREPB"},
        {StringMapper::Identifier::RDA, "RDA"},
        {StringMapper::Identifier::WRA, "WRA"},
        {StringMapper::Identifier::REFPB, "REFPB"},
        {StringMapper::Identifier::REFP2B, "REFP2B"},
        {StringMapper::Identifier::PRESB, "PRESB"},
        {StringMapper::Identifier::RFMAB, "RFMAB"},
        {StringMapper::Identifier::REFSB, "REFSB"},
        {StringMapper::Identifier::RFMSB, "RFMSB"},
    };

    auto it = enumToStr.find(id);
    if (it != enumToStr.end()) return it->second;
    else throw std::invalid_argument("The provided StringMapper::StringMapper::Identifier is not valid.");

}

StringMapper::Identifier StringMapper::getIDEnum(const QString& id) {
    static const std::map<QString, StringMapper::Identifier, QStringsComparator> strToEnum {
        {"CMD_BUS", StringMapper::Identifier::CMD_BUS},
        {"RAS_BUS", StringMapper::Identifier::RAS_BUS},
        {"CAS_BUS", StringMapper::Identifier::CAS_BUS},
        {"NAW", StringMapper::Identifier::NAW},
        {"FAW", StringMapper::Identifier::FAW},
        {"32AW", StringMapper::Identifier::_32AW},
        {"FAW_LOGICAL", StringMapper::Identifier::FAW_LOGICAL},
        {"FAW_PHYSICAL", StringMapper::Identifier::FAW_PHYSICAL},
        {"REFAB", StringMapper::Identifier::REFAB},
        {"PREAB", StringMapper::Identifier::PREAB},
        {"PDEP", StringMapper::Identifier::PDEP},
        {"PDXP", StringMapper::Identifier::PDXP},
        {"SREFEN", StringMapper::Identifier::SREFEN},
        {"SREFEX", StringMapper::Identifier::SREFEX},
        {"PDEA", StringMapper::Identifier::PDEA},
        {"PDXA", StringMapper::Identifier::PDXA},
        {"SRPDEN", StringMapper::Identifier::SRPDEN},
        {"SRPDEX", StringMapper::Identifier::SRPDEX},
        {"ACT", StringMapper::Identifier::ACT},
        {"RD", StringMapper::Identifier::RD},
        {"WR", StringMapper::Identifier::WR},
        {"PREPB", StringMapper::Identifier::PREPB},
        {"RDA", StringMapper::Identifier::RDA},
        {"WRA", StringMapper::Identifier::WRA},
        {"REFPB", StringMapper::Identifier::REFPB},
        {"REFP2B", StringMapper::Identifier::REFP2B},
        {"PRESB", StringMapper::Identifier::PRESB},
        {"RFMAB", StringMapper::Identifier::RFMAB},
        {"REFSB", StringMapper::Identifier::REFSB},
        {"RFMSB", StringMapper::Identifier::RFMSB},
    };

    auto it = strToEnum.find(id);
    if (it != strToEnum.end()) return it->second;
    else throw std::invalid_argument("The provided StringMapper::Identifier '" + id.toStdString() + "' is not valid.");

}

bool StringMapper::mAuxIsPool(StringMapper::Identifier id) {
    return id == StringMapper::Identifier::CMD_BUS
            || id == StringMapper::Identifier::RAS_BUS
            || id == StringMapper::Identifier::CAS_BUS
            || id == StringMapper::Identifier::NAW
            || id == StringMapper::Identifier::FAW
            || id == StringMapper::Identifier::_32AW
            || id == StringMapper::Identifier::FAW_LOGICAL
            || id == StringMapper::Identifier::FAW_PHYSICAL;

}

bool StringMapper::operator==(const StringMapper& str2) const {
    return mIDEnum == str2.mIDEnum;
}

bool StringMapper::operator!=(const StringMapper& str2) const {
    return mIDEnum != str2.mIDEnum;
}

bool StringMapper::operator<(const StringMapper& str2) const {
    return mIDEnum < str2.mIDEnum;
}

bool StringMapper::compare(const StringMapper& str1, const StringMapper& str2) {
    return str1.getIDEnum() < str2.getIDEnum();
}

bool StringMapper::operator==(const StringMapper::Identifier& id) const {
    return mIDEnum == id;
}

bool StringMapper::operator!=(const StringMapper::Identifier& id) const {
    return mIDEnum != id;
}
