/*
 *  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 "device_info_impl.h"
#include "video_capture_config.h"
#include "trace.h"
#include <stdlib.h>

#ifndef abs
#define abs(a) (a>=0?a:-a)
#endif

namespace webrtc
{
namespace videocapturemodule
{
DeviceInfoImpl::DeviceInfoImpl(const WebRtc_Word32 id)
    : _id(id), _apiLock(*RWLockWrapper::CreateRWLock()), _lastUsedDeviceName(NULL),
      _lastUsedDeviceNameLength(0)
{
}

DeviceInfoImpl::~DeviceInfoImpl(void)
{
    _apiLock.AcquireLockExclusive();
    // Reset old capability list
    MapItem* item = NULL;
    while ((item = _captureCapabilities.Last()))
    {
        delete (VideoCaptureCapability*) item->GetItem();
        _captureCapabilities.Erase(item);
    }
    free(_lastUsedDeviceName);
    _apiLock.ReleaseLockExclusive();

    delete &_apiLock;
}
WebRtc_Word32 DeviceInfoImpl::NumberOfCapabilities(
                                        const WebRtc_UWord8* deviceUniqueIdUTF8)
{
    WEBRTC_TRACE(webrtc::kTraceModuleCall, webrtc::kTraceVideoCapture, _id,
               "NumberOfCapabilities, uniqueID %s", deviceUniqueIdUTF8);

    if (!deviceUniqueIdUTF8)
        return -1;

    _apiLock.AcquireLockShared();

    if (_lastUsedDeviceNameLength == strlen((char*) deviceUniqueIdUTF8))
    {
        // Is it the same device that is asked for again.
#if defined(WEBRTC_MAC_INTEL) || defined(WEBRTC_LINUX)
        if(strncasecmp((char*)_lastUsedDeviceName,
                       (char*) deviceUniqueIdUTF8,
                       _lastUsedDeviceNameLength)==0)
#else
        if (_strnicmp((char*) _lastUsedDeviceName,
                      (char*) deviceUniqueIdUTF8,
                      _lastUsedDeviceNameLength) == 0)
#endif
        {
            //yes
            _apiLock.ReleaseLockShared();
            return _captureCapabilities.Size();
        }
    }
    // Need to get exclusive rights to create the new capability map.
    _apiLock.ReleaseLockShared();
    WriteLockScoped cs2(_apiLock);

    WebRtc_Word32 ret = CreateCapabilityMap(deviceUniqueIdUTF8);
    return ret;
}

WebRtc_Word32 DeviceInfoImpl::GetCapability(const WebRtc_UWord8* deviceUniqueIdUTF8,
                                            const WebRtc_UWord32 deviceCapabilityNumber,
                                            VideoCaptureCapability& capability)
{
    WEBRTC_TRACE(webrtc::kTraceModuleCall, webrtc::kTraceVideoCapture, _id,
               "GetCapability capability number %d", deviceCapabilityNumber);

    if (!deviceUniqueIdUTF8)
    {
        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
                   "deviceUniqueIdUTF8 parameter not set in call to GetCapability");
        return -1;
    }
    ReadLockScoped cs(_apiLock);

    if ((_lastUsedDeviceNameLength != strlen((char*) deviceUniqueIdUTF8))
#if defined(WEBRTC_MAC_INTEL) || defined(WEBRTC_LINUX)
        || (strncasecmp((char*)_lastUsedDeviceName,
                        (char*) deviceUniqueIdUTF8,
                        _lastUsedDeviceNameLength)!=0))
#else
        || (_strnicmp((char*) _lastUsedDeviceName,
                      (char*) deviceUniqueIdUTF8,
                      _lastUsedDeviceNameLength) != 0))
#endif

    {
        _apiLock.ReleaseLockShared();
        _apiLock.AcquireLockExclusive();
        if (-1 == CreateCapabilityMap(deviceUniqueIdUTF8))
        {
            _apiLock.ReleaseLockExclusive();
            _apiLock.AcquireLockShared();
            return -1;
        }
        _apiLock.ReleaseLockExclusive();
        _apiLock.AcquireLockShared();
    }

    // Make sure the number is valid
    if (deviceCapabilityNumber >= (unsigned int) _captureCapabilities.Size())
    {
        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
                   "deviceCapabilityNumber %d is invalid in call to GetCapability",
                   deviceCapabilityNumber);
        return -1;
    }

    MapItem* item = _captureCapabilities.Find(deviceCapabilityNumber);
    if (!item)
    {
        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
                   "Failed to find capability number %d of %d possible",
                   deviceCapabilityNumber, _captureCapabilities.Size());
        return -1;
    }

    VideoCaptureCapability* capPointer =  static_cast<VideoCaptureCapability*>
                                          (item->GetItem());
    if (!capPointer)
    {
        return -1;
    }

    capability = *capPointer;
    return 0;
}

WebRtc_Word32 DeviceInfoImpl::GetBestMatchedCapability(
                                        const WebRtc_UWord8*deviceUniqueIdUTF8,
                                        const VideoCaptureCapability requested,
                                        VideoCaptureCapability& resulting)
{

    WEBRTC_TRACE(webrtc::kTraceModuleCall, webrtc::kTraceVideoCapture, _id,
               "GetBestMatchedCapability unique ID %s", deviceUniqueIdUTF8);

    if (!deviceUniqueIdUTF8)
        return -1;

    ReadLockScoped cs(_apiLock);
    if ((_lastUsedDeviceNameLength != strlen((char*) deviceUniqueIdUTF8))
#if defined(WEBRTC_MAC_INTEL) || defined(WEBRTC_LINUX)
        || (strncasecmp((char*)_lastUsedDeviceName,
                        (char*) deviceUniqueIdUTF8,
                        _lastUsedDeviceNameLength)!=0))
#else
        || (_strnicmp((char*) _lastUsedDeviceName,
                      (char*) deviceUniqueIdUTF8,
                      _lastUsedDeviceNameLength) != 0))
#endif
    {
        _apiLock.ReleaseLockShared();
        _apiLock.AcquireLockExclusive();
        if (-1 == CreateCapabilityMap(deviceUniqueIdUTF8))
        {
            return -1;
        }
        _apiLock.ReleaseLockExclusive();
        _apiLock.AcquireLockShared();
    }

    WebRtc_Word32 bestformatIndex = -1;
    WebRtc_Word32 bestWidth = 0;
    WebRtc_Word32 bestHeight = 0;
    WebRtc_Word32 bestFrameRate = 0;
    RawVideoType bestRawType = kVideoUnknown;
    webrtc::VideoCodecType bestCodecType = webrtc::kVideoCodecUnknown;

    const WebRtc_Word32 numberOfCapabilies = _captureCapabilities.Size();

    for (WebRtc_Word32 tmp = 0; tmp < numberOfCapabilies; ++tmp) // Loop through all capabilities
    {
        MapItem* item = _captureCapabilities.Find(tmp);
        if (!item)
            return -1;

        VideoCaptureCapability& capability = *static_cast<VideoCaptureCapability*>
                                              (item->GetItem());

        const WebRtc_Word32 diffWidth = capability.width - requested.width;
        const WebRtc_Word32 diffHeight = capability.height - requested.height;
        const WebRtc_Word32 diffFrameRate = capability.maxFPS - requested.maxFPS;

        const WebRtc_Word32 currentbestDiffWith = bestWidth - requested.width;
        const WebRtc_Word32 currentbestDiffHeight = bestHeight - requested.height;
        const WebRtc_Word32 currentbestDiffFrameRate = bestFrameRate - requested.maxFPS;

        if ((diffHeight >= 0 && diffHeight <= abs(currentbestDiffHeight)) // Height better or equalt that previouse.
            || (currentbestDiffHeight < 0 && diffHeight >= currentbestDiffHeight))
        {

            if (diffHeight == currentbestDiffHeight) // Found best height. Care about the width)
            {
                if ((diffWidth >= 0 && diffWidth <= abs(currentbestDiffWith)) // Width better or equal
                    || (currentbestDiffWith < 0 && diffWidth >= currentbestDiffWith))
                {
                    if (diffWidth == currentbestDiffWith && diffHeight
                        == currentbestDiffHeight) // Same size as previously
                    {
                        //Also check the best frame rate if the diff is the same as previouse
                        if (((diffFrameRate >= 0 &&
                              diffFrameRate <= currentbestDiffFrameRate) // Frame rate to high but better match than previouse and we have not selected IUV
                            ||
                            (currentbestDiffFrameRate < 0 &&
                             diffFrameRate >= currentbestDiffFrameRate)) // Current frame rate is lower than requested. This is better.
                        )
                        {
                            if ((currentbestDiffFrameRate == diffFrameRate) // Same frame rate as previous  or frame rate allready good enough
                                || (currentbestDiffFrameRate >= 0))
                            {
                                if (bestRawType != requested.rawType
                                    && requested.rawType != kVideoUnknown
                                    && (capability.rawType == requested.rawType
                                        || capability.rawType == kVideoI420
                                        || capability.rawType == kVideoYUY2
                                        || capability.rawType == kVideoYV12))
                                {
                                    bestCodecType = capability.codecType;
                                    bestRawType = capability.rawType;
                                    bestformatIndex = tmp;
                                }
                                // If width height and frame rate is full filled we can use the camera for encoding if it is supported.
                                if (capability.height == requested.height
                                    && capability.width == requested.width
                                    && capability.maxFPS >= requested.maxFPS)
                                {
                                    if (capability.codecType == requested.codecType
                                        && bestCodecType != requested.codecType)
                                    {
                                        bestCodecType = capability.codecType;
                                        bestformatIndex = tmp;
                                    }
                                }
                            }
                            else // Better frame rate
                            {
                                if (requested.codecType == capability.codecType)
                                {

                                    bestWidth = capability.width;
                                    bestHeight = capability.height;
                                    bestFrameRate = capability.maxFPS;
                                    bestCodecType = capability.codecType;
                                    bestRawType = capability.rawType;
                                    bestformatIndex = tmp;
                                }
                            }
                        }
                    }
                    else // Better width than previously
                    {
                        if (requested.codecType == capability.codecType)
                        {
                            bestWidth = capability.width;
                            bestHeight = capability.height;
                            bestFrameRate = capability.maxFPS;
                            bestCodecType = capability.codecType;
                            bestRawType = capability.rawType;
                            bestformatIndex = tmp;
                        }
                    }
                }// else width no good
            }
            else // Better height
            {
                if (requested.codecType == capability.codecType)
                {
                    bestWidth = capability.width;
                    bestHeight = capability.height;
                    bestFrameRate = capability.maxFPS;
                    bestCodecType = capability.codecType;
                    bestRawType = capability.rawType;
                    bestformatIndex = tmp;
                }
            }
        }// else height not good
    }//end for

    WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id,
               "Best camera format: Width %d, Height %d, Frame rate %d, Color format %d",
               bestWidth, bestHeight, bestFrameRate, bestRawType);

    // Copy the capability
    MapItem* item = _captureCapabilities.Find(bestformatIndex);
    if (!item)
        return -1;
    VideoCaptureCapability* capPointer =
        static_cast<VideoCaptureCapability*> (item->GetItem());
    if (!capPointer)
        return -1;

    resulting = *capPointer;

    return bestformatIndex;
}

/* Returns the expected Capture delay*/
WebRtc_Word32 DeviceInfoImpl::GetExpectedCaptureDelay(
                                          const DelayValues delayValues[],
                                          const WebRtc_UWord32 sizeOfDelayValues,
                                          const WebRtc_UWord8* productId,
                                          const WebRtc_UWord32 width,
                                          const WebRtc_UWord32 height)
{
    WebRtc_Word32 bestDelay = kDefaultCaptureDelay;

    for (WebRtc_UWord32 device = 0; device < sizeOfDelayValues; ++device)
    {
        if (delayValues[device].productId && strncmp((char*) productId,
                                                     (char*) delayValues[device].productId,
                                                     kVideoCaptureProductIdLength) == 0)
        {
            // We have found the camera

            WebRtc_Word32 bestWidth = 0;
            WebRtc_Word32 bestHeight = 0;

            //Loop through all tested sizes and find one that seems fitting
            for (WebRtc_UWord32 delayIndex = 0; delayIndex < NoOfDelayValues; ++delayIndex)
            {
                const DelayValue& currentValue = delayValues[device].delayValues[delayIndex];

                const WebRtc_Word32 diffWidth = currentValue.width - width;
                const WebRtc_Word32 diffHeight = currentValue.height - height;

                const WebRtc_Word32 currentbestDiffWith = bestWidth - width;
                const WebRtc_Word32 currentbestDiffHeight = bestHeight - height;

                if ((diffHeight >= 0 && diffHeight <= abs(currentbestDiffHeight)) // Height better or equal than previous.
                    || (currentbestDiffHeight < 0 && diffHeight >= currentbestDiffHeight))
                {

                    if (diffHeight == currentbestDiffHeight) // Found best height. Care about the width)
                    {
                        if ((diffWidth >= 0 && diffWidth <= abs(currentbestDiffWith)) // Width better or equal
                            || (currentbestDiffWith < 0 && diffWidth >= currentbestDiffWith))
                        {
                            if (diffWidth == currentbestDiffWith && diffHeight
                                == currentbestDiffHeight) // Same size as previous
                            {
                            }
                            else // Better width than previously
                            {
                                bestWidth = currentValue.width;
                                bestHeight = currentValue.height;
                                bestDelay = currentValue.delay;
                            }
                        }// else width no good
                    }
                    else // Better height
                    {
                        bestWidth = currentValue.width;
                        bestHeight = currentValue.height;
                        bestDelay = currentValue.delay;
                    }
                }// else height not good
            }//end for
            break;
        }
    }
    if (bestDelay > kMaxCaptureDelay)
    {
        WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, _id,
                   "Expected capture delay too high. %dms, will use %d", bestDelay,
                   kMaxCaptureDelay);
        bestDelay = kMaxCaptureDelay;

    }

    return bestDelay;

}

//Default implementation. This should be overridden by Mobile implementations.
WebRtc_Word32 DeviceInfoImpl::GetOrientation(const WebRtc_UWord8* deviceUniqueIdUTF8,
                                             VideoCaptureRotation& orientation)
{
    orientation = kCameraRotate0;
    return -1;
}
} //namespace videocapturemodule
} // namespace webrtc


