#include "sdolist.h"

#include <iostream>

ClassImp(PendingSDO);
ClassImp(PendingSDOList);

using namespace std;

PendingSDOList::PendingSDOList()
{
    fFirst = new PendingSDO;
    fLast  = fFirst;
}

PendingSDOList::~PendingSDOList()
{
    DelAll();
    delete fFirst;
}

void PendingSDOList::DelAll()
{
    if (fMux.Lock()==13)
        cout << "PendingSDOList::DelAll - mutex is already locked by this thread" << endl;

    PendingSDO *prev = fFirst;
    PendingSDO *sdo;

    do
    {
        sdo = prev->Next;
        delete prev;

    } while((prev=sdo));

    fFirst = new PendingSDO;
    fLast  = fFirst;

    if (fMux.UnLock()==13)
        cout << "PendingSDOList::DelAll - tried to unlock mutex locked by other thread." << endl;
}

void PendingSDOList::Add(BYTE_t node, WORD_t idx, BYTE_t subidx)
{
    PendingSDO *sdo = fFirst;

    if (fMux.Lock()==13)
        cout << "PendingSDOList::Add - mutex is already locked by this thread" << endl;
    while ((sdo=sdo->Next))
        if (sdo->Node==node && sdo->Idx==idx && sdo->Subidx==subidx)
        {
            cout << "Warning: SDO Node #" << dec << (int)node << ", 0x";
            cout << hex << idx << "/" << (int)subidx;
            cout << " still pending." << endl;
            break;
        }

    fLast->Next = new PendingSDO(node, idx, subidx);
    fLast = fLast->Next;
    if (fMux.UnLock()==13)
        cout << "PendingSDOList::Add - tried to unlock mutex locked by other thread." << endl;
}

void PendingSDOList::Del(BYTE_t node, WORD_t idx, BYTE_t subidx)
{
    PendingSDO *prev = fFirst;
    PendingSDO *sdo;

    if (fMux.Lock()==13)
        cout << "PendingSDOList::Del - mutex is already locked by this thread" << endl;
    while ((sdo=prev->Next))
    {
        if (sdo->Node!=node || sdo->Idx!=idx || sdo->Subidx!=subidx)
        {
            prev = sdo;
            continue;
        }

        prev->Next = sdo->Next;

        delete sdo;

        if (!prev->Next)
            fLast = prev;

        break;
    }
    if (fMux.UnLock()==13)
        cout << "PendingSDOList::Del - tried to unlock mutex locked by other thread." << endl;
}

int PendingSDOList::IsPending() const
{
    return fFirst->Next ? 1 : 0;
}

int PendingSDOList::IsPending(BYTE_t node)
{
    int rc = FALSE;
    PendingSDO *sdo = fFirst;

    if (fMux.Lock()==13)
        cout << "PendingSDOList::IsPending(byte) - mutex is already locked by this thread" << endl;
    while ((sdo=sdo->Next))
        if (sdo->Node==node)
        {
            rc = TRUE;
            break;
        }
    if (fMux.UnLock()==13)
        cout << "PendingSDOList::IsPending(byte) - tried to unlock mutex locked by other thread." << endl;

    return rc;
}

int PendingSDOList::IsPending(BYTE_t node, WORD_t idx, BYTE_t subidx)
{
    int rc = FALSE;
    PendingSDO *sdo = fFirst;

    if (fMux.Lock()==13)
        cout << "PendingSDOList::IsPending - mutex is already locked by this thread" << endl;
    while ((sdo=sdo->Next))
        if (sdo->Node==node && sdo->Idx==idx && sdo->Subidx==subidx)
        {
            rc = TRUE;
            break;
        }
    if (fMux.UnLock()==13)
        cout << "PendingSDOList::IsPending - tried to unlock mutex locked by other thread." << endl;

    return rc;
}
