/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "udp_socket_manager_windows.h"
#include "udp_socket_windows.h"

namespace webrtc {
WebRtc_UWord32 UdpSocketManagerWindows::_numOfActiveManagers = 0;

UdpSocketManagerWindows::UdpSocketManagerWindows()
    : UdpSocketManager(),
      _id(-1)
{
    const WebRtc_Word8* threadName = "UdpSocketManagerWindows_Thread";
    _critSectList = CriticalSectionWrapper::CreateCriticalSection();
    _thread = ThreadWrapper::CreateThread(UdpSocketManagerWindows::Run,
                                          this, kRealtimePriority, threadName);
    FD_ZERO(&_readFds);
    FD_ZERO(&_writeFds);
    FD_ZERO(&_exceptFds);
    _numOfActiveManagers++;
}

bool UdpSocketManagerWindows::Init(WebRtc_Word32 id,
                                   WebRtc_UWord8& numOfWorkThreads) {
    CriticalSectionScoped cs(_critSectList);
    if ((_id != -1) || (_numOfWorkThreads != 0)) {
        assert(_id == -1);
        assert(_numOfWorkThreads == 0);
        return false;
    }
    _id = id;
    _numOfWorkThreads = numOfWorkThreads;
    return true;
}

UdpSocketManagerWindows::~UdpSocketManagerWindows()
{
    Stop();
    if(_thread != NULL)
    {
        delete _thread;
    }

    if (_critSectList != NULL)
    {
        _critSectList->Enter();

        while(!_socketMap.empty())
        {
            std::map<SOCKET, UdpSocketWindows*>::iterator it =
                _socketMap.begin();
            UdpSocketWindows* s = static_cast<UdpSocketWindows*>(it->second);
            _socketMap.erase(it);
            delete s;
        }
        _removeList.erase(_removeList.begin(), _removeList.end());

        while(!_addList.empty())
        {
            std::list<UdpSocketWindows*>::iterator it = _addList.begin();
            UdpSocketWindows* s = static_cast<UdpSocketWindows*>(*it);
            _addList.erase(it);
            delete s;
        }
        _critSectList->Leave();

        delete _critSectList;
    }

    _numOfActiveManagers--;

    if (_numOfActiveManagers == 0)
        WSACleanup();
}

WebRtc_Word32 UdpSocketManagerWindows::ChangeUniqueId(const WebRtc_Word32 id)
{
    _id = id;
    return 0;
}

bool UdpSocketManagerWindows::Start()
{
    unsigned int id;
    if (_thread == NULL)
        return false;

    return _thread->Start(id);
}

bool UdpSocketManagerWindows::Stop()
{
    if (_thread == NULL)
        return true;

    return _thread->Stop();
}

bool UdpSocketManagerWindows::Process()
{
    bool doSelect = false;
    // Timeout = 1 second.
    timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = 10000;

    FD_ZERO(&_readFds);
    FD_ZERO(&_writeFds);
    FD_ZERO(&_exceptFds);

    _critSectList->Enter();
    // Remove sockets that have been registered for removal.
    while(!_removeList.empty())
    {
        SOCKET id = *_removeList.begin();
        std::map<SOCKET, UdpSocketWindows*>::iterator it = _socketMap.find(id);
        if(it != _socketMap.end())
        {
            UdpSocketWindows* s = static_cast<UdpSocketWindows*>(it->second);
            _socketMap.erase(it);
            _removeList.pop_front();
            delete s;
        }
    }

    // Add sockets that have been registered for being added.
    while (!_addList.empty())
    {
        UdpSocketWindows* s = *_addList.begin();
        if(s)
        {
            _socketMap[s->GetFd()] = s;
        }
        _addList.pop_front();
    }
    _critSectList->Leave();

    std::map<SOCKET, UdpSocketWindows*>::iterator it = _socketMap.begin();
    while(it != _socketMap.end())
    {
        UdpSocketWindows* s = it->second;
        if (s->WantsIncoming())
        {
            doSelect = true;
            FD_SET(it->first, &_readFds);
        }
        if(!s->IsWritable())
        {
            FD_SET(it->first, &_writeFds);
            doSelect = true;
        }
        it++;
    }

    WebRtc_Word32 num = 0;
    if (doSelect)
    {
        num = select(0, &_readFds, &_writeFds, &_exceptFds, &timeout);
        if (num == SOCKET_ERROR)
        {
            Sleep(10);
            return true;
        }
    }else
    {
        Sleep(10);
        return true;
    }

    it = _socketMap.begin();
    while (it != _socketMap.end() && num > 0)
    {
        if (FD_ISSET(it->first, &_readFds))
        {
            static_cast<UdpSocketWindows*>(it->second)->HasIncoming();
            num--;
        }
        if (FD_ISSET(it->first, &_writeFds))
        {
            // Socket available for writing.
            static_cast<UdpSocketWindows*>(it->second)->SetWritable();
            num--;
        }
    }
    return true;
}

bool UdpSocketManagerWindows::Run(ThreadObj obj)
{
    UdpSocketManagerWindows* mgr = static_cast<UdpSocketManagerWindows*>(obj);
    return mgr->Process();
};

bool UdpSocketManagerWindows::AddSocket(UdpSocketWrapper* s)
{
    UdpSocketWindows* winSock = static_cast<UdpSocketWindows*>(s);

    _critSectList->Enter();
    std::map<SOCKET, UdpSocketWindows*>::iterator it =
        _socketMap.find(winSock->GetFd());
    if (it != _socketMap.end())
    {
        if (!_removeList.empty())
        {
            // File descriptors are re-used so it's possible that a socket has
            // been added with the same file descriptor as a socket that is to
            // be removed. I.e. the socket that is to be removed is no longer
            // in use, delete it.
            // TODO (hellner): removing items from _socketMap may cause race
            // condition. Fix this.
            std::list<SOCKET>::iterator removeIt = _removeList.begin();
            while(removeIt != _removeList.end())
            {
                if (*removeIt == winSock->GetFd())
                {
                    it = _socketMap.find(*removeIt);
                    UdpSocketWindows* delete_socket = it->second;
                    _socketMap.erase(it);
                    _removeList.erase(removeIt);
                    delete delete_socket;
                    _addList.push_back(winSock);
                    _critSectList->Leave();
                    return true;
                }
                removeIt++;
            }
        }
        _critSectList->Leave();
        return false;
    }

    _addList.push_back(winSock);
    _critSectList->Leave();
    return true;
}

bool UdpSocketManagerWindows::RemoveSocket(UdpSocketWrapper* s)
{
    UdpSocketWindows* winSock = static_cast<UdpSocketWindows*>(s);

    _critSectList->Enter();
    // If socket is in the add list its safe to just remove it from the list.
    if (!_addList.empty())
    {
        std::list<UdpSocketWindows*>::iterator it = _addList.begin();
        while(it != _addList.end())
        {
            UdpSocketWindows* tempSocket = (*it);
            if (tempSocket->GetFd() == winSock->GetFd())
            {
                _addList.erase(it);
                delete winSock;
                _critSectList->Leave();
                return true;
            }
            it++;
        }
    }

    // If the socket is not even added to the UdpSocketManagerWindows it's
    // safe to delete the socket.
    std::map<SOCKET, UdpSocketWindows*>::iterator findIt =
        _socketMap.find(winSock->GetFd());
    if (findIt == _socketMap.end())
    {
        delete winSock;
        _critSectList->Leave();
        return false;
    }

    _removeList.push_back(winSock->GetFd());
    _critSectList->Leave();
    return true;
}
} // namespace webrtc
