#include "LocalPoolOwnerBase.h"

LocalPoolOwnerBase::LocalPoolOwnerBase(object_id_t objectId):
        SystemObject(objectId), poolManager(this, messageQueue),
        dataset(this, lpool::testSetId) {
    messageQueue = new MessageQueueMockBase();
}

LocalPoolOwnerBase::~LocalPoolOwnerBase() {
    QueueFactory::instance()->deleteMessageQueue(messageQueue);
}

ReturnValue_t LocalPoolOwnerBase::initializeHkManager() {
    if(not initialized) {
        initialized = true;
        return poolManager.initialize(messageQueue);
    }
    return HasReturnvaluesIF::RETURN_OK;
}

ReturnValue_t LocalPoolOwnerBase::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
        LocalDataPoolManager &poolManager) {

    // Default initialization empty for now.
    localDataPoolMap.emplace(lpool::uint8VarId,
            new PoolEntry<uint8_t>({0}));
    localDataPoolMap.emplace(lpool::floatVarId,
            new PoolEntry<float>({0}));
    localDataPoolMap.emplace(lpool::uint32VarId,
            new PoolEntry<uint32_t>({0}));

    localDataPoolMap.emplace(lpool::uint16Vec3Id,
            new PoolEntry<uint16_t>({0, 0, 0}));
    localDataPoolMap.emplace(lpool::int64Vec2Id,
            new PoolEntry<int64_t>({0, 0}));
    return HasReturnvaluesIF::RETURN_OK;
}

LocalPoolObjectBase* LocalPoolOwnerBase::getPoolObjectHandle(lp_id_t localPoolId) {
    if(localPoolId == lpool::uint8VarId) {
        return &testUint8;
    }
    else if(localPoolId == lpool::uint16Vec3Id) {
        return &testUint16Vec;
    }
    else if(localPoolId == lpool::floatVarId) {
        return &testFloat;
    }
    else if(localPoolId == lpool::int64Vec2Id) {
        return &testInt64Vec;
    }
    else if(localPoolId == lpool::uint32VarId) {
        return &testUint32;
    }
    else {
        return &testUint8;
    }
}

ReturnValue_t LocalPoolOwnerBase::reset() {
    resetSubscriptionList();
    ReturnValue_t status = HasReturnvaluesIF::RETURN_OK;
    {
        PoolReadGuard readHelper(&dataset);
        if(readHelper.getReadResult() != HasReturnvaluesIF::RETURN_OK) {
            status = readHelper.getReadResult();
        }
        dataset.localPoolVarUint8.value = 0;
        dataset.localPoolVarFloat.value = 0.0;
        dataset.localPoolUint16Vec.value[0] = 0;
        dataset.localPoolUint16Vec.value[1] = 0;
        dataset.localPoolUint16Vec.value[2] = 0;
        dataset.setValidity(false, true);
    }

    {
        PoolReadGuard readHelper(&testUint32);
        if(readHelper.getReadResult() != HasReturnvaluesIF::RETURN_OK) {
            status = readHelper.getReadResult();
        }
        testUint32.value = 0;
        testUint32.setValid(false);
    }

    {
        PoolReadGuard readHelper(&testInt64Vec);
        if(readHelper.getReadResult() != HasReturnvaluesIF::RETURN_OK) {
            status = readHelper.getReadResult();
        }
        testInt64Vec.value[0] = 0;
        testInt64Vec.value[1] = 0;
        testInt64Vec.setValid(false);
    }
    return status;
}

bool LocalPoolOwnerBase::changedDataSetCallbackWasCalled(sid_t &sid, store_address_t &storeId) {
    bool condition = false;
    if(not this->changedDatasetSid.notSet()) {
        condition = true;
    }
    sid = changedDatasetSid;
    storeId = storeIdForChangedSet;
    this->changedDatasetSid.raw = sid_t::INVALID_SID;
    this->storeIdForChangedSet = storeId::INVALID_STORE_ADDRESS;
    return condition;
}

void LocalPoolOwnerBase::handleChangedDataset(sid_t sid, store_address_t storeId,
        bool* clearMessage) {
    this->changedDatasetSid = sid;
    this->storeIdForChangedSet = storeId;
}

bool LocalPoolOwnerBase::changedVariableCallbackWasCalled(gp_id_t &gpid, store_address_t &storeId) {
    bool condition = false;
    if(not this->changedPoolVariableGpid.notSet()) {
        condition = true;
    }
    gpid = changedPoolVariableGpid;
    storeId = storeIdForChangedVariable;
    this->changedPoolVariableGpid.raw = gp_id_t::INVALID_GPID;
    this->storeIdForChangedVariable = storeId::INVALID_STORE_ADDRESS;
    return condition;
}

ReturnValue_t LocalPoolOwnerBase::initializeHkManagerAfterTaskCreation() {
    if(not initializedAfterTaskCreation) {
        initializedAfterTaskCreation = true;
        return poolManager.initializeAfterTaskCreation();
    }
    return HasReturnvaluesIF::RETURN_OK;

}

void LocalPoolOwnerBase::handleChangedPoolVariable(gp_id_t globPoolId, store_address_t storeId,
        bool* clearMessage) {
    this->changedPoolVariableGpid = globPoolId;
    this->storeIdForChangedVariable = storeId;
}