/*
 *  Copyright (c) 2012 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 "webrtc/modules/video_render/linux/video_x11_channel.h"
#include "webrtc/modules/video_render/linux/video_x11_render.h"

#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
#include "webrtc/system_wrappers/include/trace.h"

namespace webrtc {

VideoX11Render::VideoX11Render(Window window) :
    _window(window),
            _critSect(*CriticalSectionWrapper::CreateCriticalSection())
{
}

VideoX11Render::~VideoX11Render()
{
    delete &_critSect;
}

int32_t VideoX11Render::Init()
{
    CriticalSectionScoped cs(&_critSect);

    _streamIdToX11ChannelMap.clear();

    return 0;
}

int32_t VideoX11Render::ChangeWindow(Window window)
{
    CriticalSectionScoped cs(&_critSect);
    VideoX11Channel* renderChannel = NULL;

    std::map<int, VideoX11Channel*>::iterator iter =
            _streamIdToX11ChannelMap.begin();

    while (iter != _streamIdToX11ChannelMap.end())
    {
        renderChannel = iter->second;
        if (renderChannel)
        {
            renderChannel->ChangeWindow(window);
        }
        iter++;
    }

    _window = window;

    return 0;
}

VideoX11Channel* VideoX11Render::CreateX11RenderChannel(
                                                                int32_t streamId,
                                                                int32_t zOrder,
                                                                const float left,
                                                                const float top,
                                                                const float right,
                                                                const float bottom)
{
    CriticalSectionScoped cs(&_critSect);
    VideoX11Channel* renderChannel = NULL;

    std::map<int, VideoX11Channel*>::iterator iter =
            _streamIdToX11ChannelMap.find(streamId);

    if (iter == _streamIdToX11ChannelMap.end())
    {
        renderChannel = new VideoX11Channel(streamId);
        if (!renderChannel)
        {
            WEBRTC_TRACE(
                         kTraceError,
                         kTraceVideoRenderer,
                         -1,
                         "Failed to create VideoX11Channel for streamId : %d",
                         streamId);
            return NULL;
        }
        renderChannel->Init(_window, left, top, right, bottom);
        _streamIdToX11ChannelMap[streamId] = renderChannel;
    }
    else
    {
        WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, -1,
                     "Render Channel already exists for streamId: %d", streamId);
        renderChannel = iter->second;
    }

    return renderChannel;
}

int32_t VideoX11Render::DeleteX11RenderChannel(int32_t streamId)
{
    CriticalSectionScoped cs(&_critSect);

    std::map<int, VideoX11Channel*>::iterator iter =
            _streamIdToX11ChannelMap.find(streamId);
    if (iter != _streamIdToX11ChannelMap.end())
    {
        VideoX11Channel *renderChannel = iter->second;
        if (renderChannel)
        {
            renderChannel->ReleaseWindow();
            delete renderChannel;
            renderChannel = NULL;
        }
        _streamIdToX11ChannelMap.erase(iter);
    }

    WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, -1,
                 "No VideoX11Channel object exists for stream id: %d",
                 streamId);
    return -1;
}

int32_t VideoX11Render::GetIncomingStreamProperties(
                                                              int32_t streamId,
                                                              uint32_t& zOrder,
                                                              float& left,
                                                              float& top,
                                                              float& right,
                                                              float& bottom)
{
    CriticalSectionScoped cs(&_critSect);

    std::map<int, VideoX11Channel*>::iterator iter =
            _streamIdToX11ChannelMap.find(streamId);
    if (iter != _streamIdToX11ChannelMap.end())
    {
        VideoX11Channel *renderChannel = iter->second;
        if (renderChannel)
        {
            renderChannel->GetStreamProperties(zOrder, left, top, right, bottom);
        }
    }

    WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, -1,
                 "No VideoX11Channel object exists for stream id: %d",
                 streamId);
    return -1;
}

}  // namespace webrtc
