#pragma once

#include <boost/algorithm/string.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/endian/conversion.hpp>
#include <filesystem>
#include <fstream>
#include <nlohmann/json.hpp>

namespace crow
{
namespace ibm_mc_lock
{

namespace fs = std::filesystem;
using SType = std::string;

/*----------------------------------------
|Segment flags : LockFlag | SegmentLength|
------------------------------------------*/

using SegmentFlags = std::vector<std::pair<SType, uint32_t>>;

// Lockrequest = session-id | hmc-id | locktype | resourceid | segmentinfo
using LockRequest = std::tuple<SType, SType, SType, uint64_t, SegmentFlags>;
using LockRequests = std::vector<LockRequest>;
using Rc =
    std::pair<bool, std::variant<uint32_t, std::pair<uint32_t, LockRequest>>>;
using RcRelaseLock = std::pair<bool, std::pair<uint32_t, LockRequest>>;
using RcGetLockList =
    std::variant<std::string, std::vector<std::pair<uint32_t, LockRequests>>>;
using ListOfTransactionIds = std::vector<uint32_t>;
using RcAcquireLock = std::pair<bool, std::variant<Rc, std::pair<bool, int>>>;
using RcReleaseLockApi = std::pair<bool, std::variant<bool, RcRelaseLock>>;
using SessionFlags = std::pair<SType, SType>;
using ListOfSessionIds = std::vector<std::string>;
static constexpr const char *fileName =
    "/var/lib/obmc/bmc-console-mgmt/locks/ibm_mc_persistent_lock_data.json";

class Lock
{
    uint32_t transactionId;
    boost::container::flat_map<uint32_t, LockRequests> lockTable;

    /*
     * This function implements the logic for validating an incoming
     * lock request/requests.
     *
     * Returns : True (if Valid)
     * Returns : False (if not a Valid lock request)
     */

    bool isValidLockRequest(const LockRequest);

    /*
     * This function implements the logic of checking if the incoming
     * multi-lock request is not having conflicting requirements.
     *
     * Returns : True (if conflicting)
     * Returns : False (if not conflicting)
     */

    bool isConflictRequest(const LockRequests);
    /*
     * Implements the core algorithm to find the conflicting
     * lock requests.
     *
     * This functions takes two lock requests and check if both
     * are conflicting to each other.
     *
     * Returns : True (if conflicting)
     * Returns : False (if not conflicting)
     */
    bool isConflictRecord(const LockRequest, const LockRequest);

    /*
     * This function implements the logic of checking the conflicting
     * locks from a incoming single/multi lock requests with the already
     * existing lock request in the lock table.
     *
     */

    Rc isConflictWithTable(const LockRequests);
    /*
     * This function implements the logic of checking the ownership of the
     * lock from the releaselock request.
     *
     * Returns : True (if the requesting HMC & Session owns the lock(s))
     * Returns : False (if the request HMC or Session does not own the lock(s))
     */

    RcRelaseLock isItMyLock(const ListOfTransactionIds &, const SessionFlags &);

    /*
     * This function validates the the list of transactionID's and returns false
     * if the transaction ID is not valid & not present in the lock table
     */

    bool validateRids(const ListOfTransactionIds &);

    /*
     * This function releases the locks that are already obtained by the
     * requesting Management console.
     */

    void releaseLock(const ListOfTransactionIds &);

    /*
     * This API implements the logic to persist the locks that are contained in
     * the lock table into a json file.
     */
    void saveLocks();

    /*
     * This API implements the logic to load the locks that are present in the
     * json file into the lock table.
     */
    void loadLocks();

    /*
     * This function implements the algorithm for checking the respective
     * bytes of the resource id based on the lock management algorithm.
     */

    bool checkByte(uint64_t, uint64_t, uint32_t);

    /*
     * This functions implements a counter that generates a unique 32 bit
     * number for every successful transaction. This number will be used by
     * the Management Console for debug.
     */
    uint32_t generateTransactionId();

    bool createPersistentLockFilePath();

  public:
    /*
     * This function implements the logic for acquiring a lock on a
     * resource if the incoming request is legitimate without any
     * conflicting requirements & without any conflicting requirement
     * with the exsiting locks in the lock table.
     *
     */

    RcAcquireLock acquireLock(const LockRequests);

    /*
     * This function implements the logic for releasing the lock that are
     * owned by a management console session.
     *
     * The locks can be released by two ways
     *  - Using list of transaction ID's
     *  - Using a Session ID
     *
     * Client can choose either of the ways by using `Type` JSON key.
     *
     */
    RcReleaseLockApi releaseLock(const ListOfTransactionIds &,
                                 const SessionFlags &);

    /*
     * This function implements the logic for getting the list of locks obtained
     * by a particular management console.
     */
    RcGetLockList getLockList(const ListOfSessionIds &);

    /*
     * This function is releases all the locks obtained by a particular
     * session.
     */

    void releaseLock(const std::string &);

    Lock()
    {
        loadLocks();
        transactionId = lockTable.empty() ? 0 : prev(lockTable.end())->first;
    }

    static Lock &getInstance()
    {
        static Lock lockObject;
        return lockObject;
    }
};

inline bool Lock::createPersistentLockFilePath()
{
    // The path /var/lib/obmc will be created by initrdscripts
    // Create the directories for the persistent lock file
    std::error_code ec;
    if (!std::filesystem::is_directory("/var/lib/obmc/bmc-console-mgmt", ec))
    {
        std::filesystem::create_directory("/var/lib/obmc/bmc-console-mgmt", ec);
    }
    if (ec)
    {
        BMCWEB_LOG_DEBUG
            << "Failed to prepare bmc-console-mgmt directory. ec : " << ec;
        return false;
    }

    if (!std::filesystem::is_directory("/var/lib/obmc/bmc-console-mgmt/locks",
                                       ec))
    {
        std::filesystem::create_directory(
            "/var/lib/obmc/bmc-console-mgmt/locks", ec);
    }
    if (ec)
    {
        BMCWEB_LOG_DEBUG
            << "Failed to prepare persistent lock file directory. ec : " << ec;
        return false;
    }
    return true;
}

inline void Lock::loadLocks()
{
    std::ifstream persistentFile(fileName);
    if (persistentFile.is_open())
    {
        auto data = nlohmann::json::parse(persistentFile, nullptr, false);
        if (data.is_discarded())
        {
            BMCWEB_LOG_ERROR << "Error parsing persistent data in json file.";
            return;
        }
        BMCWEB_LOG_DEBUG << "The persistent lock data is available";
        for (const auto &item : data.items())
        {
            BMCWEB_LOG_DEBUG << item.key();
            BMCWEB_LOG_DEBUG << item.value();
            LockRequests locks = item.value();
            lockTable.emplace(std::pair<uint32_t, LockRequests>(
                std::stoul(item.key()), locks));
            BMCWEB_LOG_DEBUG << "The persistent lock data loaded";
        }
    }
}

inline void Lock::saveLocks()
{
    std::error_code ec;
    if (!std::filesystem::is_directory("/var/lib/obmc/bmc-console-mgmt/locks",
                                       ec))
    {
        if (!createPersistentLockFilePath())
        {
            BMCWEB_LOG_DEBUG << "Failed to create lock persistent path";
            return;
        }
    }
    std::ofstream persistentFile(fileName);
    // set the permission of the file to 640
    fs::perms permission =
        fs::perms::owner_read | fs::perms::owner_write | fs::perms::group_read;
    fs::permissions(fileName, permission);
    nlohmann::json data;
    for (const auto &it : lockTable)
    {
        data[std::to_string(it.first)] = it.second;
    }
    BMCWEB_LOG_DEBUG << "data is " << data;
    persistentFile << data;
}

inline RcGetLockList Lock::getLockList(const ListOfSessionIds &listSessionId)
{

    std::vector<std::pair<uint32_t, LockRequests>> lockList;

    if (!lockTable.empty())
    {
        for (const auto &i : listSessionId)
        {
            auto it = lockTable.begin();
            while (it != lockTable.end())
            {
                // Check if session id of this entry matches with session id
                // given
                if (std::get<0>(it->second[0]) == i)
                {
                    BMCWEB_LOG_DEBUG << "Session id is found in the locktable";

                    // Push the whole lock record into a vector for returning
                    // the json
                    lockList.push_back(std::make_pair(it->first, it->second));
                }
                // Go to next entry in map
                it++;
            }
        }
    }
    // we may have found at least one entry with the given session id
    // return the json list of lock records pertaining to the given
    // session id, or send an empty list if lock table is empty
    return lockList;
}

inline RcReleaseLockApi Lock::releaseLock(const ListOfTransactionIds &p,
                                          const SessionFlags &ids)
{

    bool status = validateRids(p);

    if (!status)
    {
        // Validation of rids failed
        BMCWEB_LOG_DEBUG << "Not a Valid request id";
        return std::make_pair(false, status);
    }
    else
    {
        // Validation passed, check if all the locks are owned by the
        // requesting HMC
        auto status = isItMyLock(p, ids);
        if (status.first)
        {
            // The current hmc owns all the locks, so we can release
            // them
            releaseLock(p);
        }
        return std::make_pair(true, status);
    }
    return std::make_pair(false, status);
}

inline RcAcquireLock Lock::acquireLock(const LockRequests lockRequestStructure)
{

    // validate the lock request

    for (auto &lockRecord : lockRequestStructure)
    {
        bool status = isValidLockRequest(lockRecord);
        if (!status)
        {
            BMCWEB_LOG_DEBUG << "Not a Valid record";
            BMCWEB_LOG_DEBUG << "Bad json in request";
            return std::make_pair(true, std::make_pair(status, 0));
        }
    }
    // check for conflict record

    const LockRequests &multiRequest = lockRequestStructure;
    bool status = isConflictRequest(multiRequest);

    if (status)
    {
        BMCWEB_LOG_DEBUG << "There is a conflict within itself";
        return std::make_pair(true, std::make_pair(status, 1));
    }
    else
    {
        BMCWEB_LOG_DEBUG << "The request is not conflicting within itself";

        // Need to check for conflict with the locktable entries.

        auto conflict = isConflictWithTable(multiRequest);

        BMCWEB_LOG_DEBUG << "Done with checking conflict with the locktable";
        return std::make_pair(false, conflict);
    }

    return std::make_pair(true, std::make_pair(true, 1));
}

inline void Lock::releaseLock(const ListOfTransactionIds &refRids)
{
    for (const auto &id : refRids)
    {
        if (lockTable.erase(id))
        {
            BMCWEB_LOG_DEBUG << "Removing the locks with transaction ID : "
                             << id;
        }

        else
        {
            BMCWEB_LOG_DEBUG << "Removing the locks from the lock table "
                                "failed, tranasction ID: "
                             << id;
        }
    }

    saveLocks();
}

inline void Lock::releaseLock(const std::string &sessionId)
{
    bool isErased = false;
    if (!lockTable.empty())
    {
        auto it = lockTable.begin();
        while (it != lockTable.end())
        {
            if (it->second.size() != 0)
            {
                // Check if session id of this entry matches with session id
                // given
                if (std::get<0>(it->second[0]) == sessionId)
                {
                    BMCWEB_LOG_DEBUG << "Remove the lock from the locktable "
                                        "having sessionID="
                                     << sessionId;
                    BMCWEB_LOG_DEBUG << "TransactionID =" << it->first;
                    it = lockTable.erase(it);
                    isErased = true;
                }
                else
                {
                    it++;
                }
            }
        }
        if (isErased)
        {
            // save the lock in the persistent file
            saveLocks();
        }
    }
}
inline RcRelaseLock Lock::isItMyLock(const ListOfTransactionIds &refRids,
                                     const SessionFlags &ids)
{
    for (const auto &id : refRids)
    {
        // Just need to compare the client id of the first lock records in the
        // complete lock row(in the map), because the rest of the lock records
        // would have the same client id

        std::string expectedClientId = std::get<1>(lockTable[id][0]);
        std::string expectedSessionId = std::get<0>(lockTable[id][0]);

        if ((expectedClientId == ids.first) &&
            (expectedSessionId == ids.second))
        {
            // It is owned by the currently request hmc
            BMCWEB_LOG_DEBUG << "Lock is owned  by the current hmc";
        }
        else
        {
            BMCWEB_LOG_DEBUG << "Lock is not owned by the current hmc";
            return std::make_pair(false, std::make_pair(id, lockTable[id][0]));
        }
    }
    return std::make_pair(true, std::make_pair(0, LockRequest()));
}

inline bool Lock::validateRids(const ListOfTransactionIds &refRids)
{
    for (const auto &id : refRids)
    {
        auto search = lockTable.find(id);

        if (search != lockTable.end())
        {
            BMCWEB_LOG_DEBUG << "Valid Transaction id";
            //  continue for the next rid
        }
        else
        {
            BMCWEB_LOG_DEBUG << "Atleast 1 inValid Request id";
            return false;
        }
    }
    return true;
}

inline bool Lock::isValidLockRequest(const LockRequest refLockRecord)
{

    // validate the locktype

    if (!((boost::equals(std::get<2>(refLockRecord), "Read") ||
           (boost::equals(std::get<2>(refLockRecord), "Write")))))
    {
        BMCWEB_LOG_DEBUG << "Validation of LockType Failed";
        BMCWEB_LOG_DEBUG << "Locktype : " << std::get<2>(refLockRecord);
        return false;
    }

    BMCWEB_LOG_DEBUG << static_cast<int>(std::get<4>(refLockRecord).size());

    // validate the number of segments
    // Allowed No of segments are between 2 and 6
    if ((static_cast<int>(std::get<4>(refLockRecord).size()) > 6) ||
        (static_cast<int>(std::get<4>(refLockRecord).size()) < 2))
    {
        BMCWEB_LOG_DEBUG << "Validation of Number of Segements Failed";
        BMCWEB_LOG_DEBUG << "Number of Segments provied : "
                         << sizeof(std::get<4>(refLockRecord));
        return false;
    }

    int lockFlag = 0;
    // validate the lockflags & segment length

    for (const auto &p : std::get<4>(refLockRecord))
    {

        // validate the lock flags
        // Allowed lockflags are locksame,lockall & dontlock

        if (!((boost::equals(p.first, "LockSame") ||
               (boost::equals(p.first, "LockAll")) ||
               (boost::equals(p.first, "DontLock")))))
        {
            BMCWEB_LOG_DEBUG << "Validation of lock flags failed";
            BMCWEB_LOG_DEBUG << p.first;
            return false;
        }

        // validate the segment length
        // Allowed values of segment length are between 1 and 4

        if (p.second < 1 || p.second > 4)
        {
            BMCWEB_LOG_DEBUG << "Validation of Segment Length Failed";
            BMCWEB_LOG_DEBUG << p.second;
            return false;
        }

        if ((boost::equals(p.first, "LockSame") ||
             (boost::equals(p.first, "LockAll"))))
        {
            ++lockFlag;
            if (lockFlag >= 2)
            {
                return false;
            }
        }
    }

    return true;
}

inline Rc Lock::isConflictWithTable(const LockRequests refLockRequestStructure)
{

    uint32_t transactionId;

    if (lockTable.empty())
    {
        transactionId = generateTransactionId();
        BMCWEB_LOG_DEBUG << transactionId;
        // Lock table is empty, so we are safe to add the lockrecords
        // as there will be no conflict
        BMCWEB_LOG_DEBUG << "Lock table is empty, so adding the lockrecords";
        lockTable.emplace(std::pair<uint32_t, LockRequests>(
            transactionId, refLockRequestStructure));

        // save the lock in the persistent file
        saveLocks();
        return std::make_pair(false, transactionId);
    }

    else
    {
        BMCWEB_LOG_DEBUG
            << "Lock table is not empty, check for conflict with lock table";
        // Lock table is not empty, compare the lockrequest entries with
        // the entries in the lock table

        for (const auto &lockRecord1 : refLockRequestStructure)
        {
            for (const auto &map : lockTable)
            {
                for (const auto &lockRecord2 : map.second)
                {
                    bool status = isConflictRecord(lockRecord1, lockRecord2);
                    if (status)
                    {
                        return std::make_pair(
                            true, std::make_pair(map.first, lockRecord2));
                    }
                }
            }
        }

        // Reached here, so no conflict with the locktable, so we are safe to
        // add the request records into the lock table

        // Lock table is empty, so we are safe to add the lockrecords
        // as there will be no conflict
        BMCWEB_LOG_DEBUG << " Adding elements into lock table";
        transactionId = generateTransactionId();
        lockTable.emplace(
            std::make_pair(transactionId, refLockRequestStructure));

        // save the lock in the persistent file
        saveLocks();
    }
    return std::make_pair(false, transactionId);
}

inline bool Lock::isConflictRequest(const LockRequests refLockRequestStructure)
{
    // check for all the locks coming in as a part of single request
    // return conflict if any two lock requests are conflicting

    if (refLockRequestStructure.size() == 1)
    {
        BMCWEB_LOG_DEBUG << "Only single lock request, so there is no conflict";
        // This means , we have only one lock request in the current
        // request , so no conflict within the request
        return false;
    }

    else
    {
        BMCWEB_LOG_DEBUG
            << "There are multiple lock requests coming in a single request";

        // There are multiple requests a part of one request

        for (uint32_t i = 0; i < refLockRequestStructure.size(); i++)
        {
            for (uint32_t j = i + 1; j < refLockRequestStructure.size(); j++)
            {
                const LockRequest &p = refLockRequestStructure[i];
                const LockRequest &q = refLockRequestStructure[j];
                bool status = isConflictRecord(p, q);

                if (status)
                {
                    return true;
                }
            }
        }
    }
    return false;
}

// This function converts the provided uint64_t resource id's from the two
// lock requests subjected for comparision, and this function also compares
// the content by bytes mentioned by a uint32_t number.

// If all the elements in the lock requests which are subjected for comparison
// are same, then the last comparision would be to check for the respective
// bytes in the resourceid based on the segment length.

inline bool Lock::checkByte(uint64_t resourceId1, uint64_t resourceId2,
                            uint32_t position)
{
    uint8_t *p = reinterpret_cast<uint8_t *>(&resourceId1);
    uint8_t *q = reinterpret_cast<uint8_t *>(&resourceId2);

    BMCWEB_LOG_DEBUG << "Comparing bytes " << std::to_string(p[position]) << ","
                     << std::to_string(q[position]);
    if (p[position] != q[position])
    {
        return false;
    }

    else
    {
        return true;
    }

    return true;
}

inline bool Lock::isConflictRecord(const LockRequest refLockRecord1,
                                   const LockRequest refLockRecord2)
{
    // No conflict if both are read locks

    if (boost::equals(std::get<2>(refLockRecord1), "Read") &&
        boost::equals(std::get<2>(refLockRecord2), "Read"))
    {
        BMCWEB_LOG_DEBUG << "Both are read locks, no conflict";
        return false;
    }

    else
    {
        uint32_t i = 0;
        for (const auto &p : std::get<4>(refLockRecord1))
        {

            // return conflict when any of them is try to lock all resources
            // under the current resource level.
            if (boost::equals(p.first, "LockAll") ||
                boost::equals(std::get<4>(refLockRecord2)[i].first, "LockAll"))
            {
                BMCWEB_LOG_DEBUG
                    << "Either of the Comparing locks are trying to lock all "
                       "resources under the current resource level";
                return true;
            }

            // determine if there is a lock-all-with-same-segment-size.
            // If the current segment sizes are the same,then we should fail.

            if ((boost::equals(p.first, "LockSame") ||
                 boost::equals(std::get<4>(refLockRecord2)[i].first,
                               "LockSame")) &&
                (p.second == std::get<4>(refLockRecord2)[i].second))
            {
                return true;
            }

            // if segment lengths are not the same, it means two different locks
            // So no conflict
            if (p.second != std::get<4>(refLockRecord2)[i].second)
            {
                BMCWEB_LOG_DEBUG << "Segment lengths are not same";
                BMCWEB_LOG_DEBUG << "Segment 1 length : " << p.second;
                BMCWEB_LOG_DEBUG << "Segment 2 length : "
                                 << std::get<4>(refLockRecord2)[i].second;
                return false;
            }

            // compare segment data

            for (uint32_t i = 0; i < p.second; i++)
            {
                // if the segment data is different , then the locks is on a
                // different resource So no conflict between the lock
                // records.
                // BMC is little endian , but the resourceID is formed by
                // the Managament Console in such a way that, the first byte
                // from the MSB Position corresponds to the First Segment
                // data. Therefore we need to convert the in-comming
                // resourceID into Big Endian before processing further.
                if (!(checkByte(boost::endian::endian_reverse(
                                    std::get<3>(refLockRecord1)),
                                boost::endian::endian_reverse(
                                    std::get<3>(refLockRecord2)),
                                i)))
                {
                    return false;
                }
            }

            ++i;
        }
    }

    return false;
}

inline uint32_t Lock::generateTransactionId()
{
    ++transactionId;
    return transactionId;
}

} // namespace ibm_mc_lock
} // namespace crow
