/*
 *  Copyright (C) 2004-2021 Savoir-faire Linux Inc.
 *
 *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 */

#include <algorithm>
#include <cassert>
#include <climits>
#include <map>
#include <string>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>

#include "logger.h"
#include "../video_device.h"

#import <AVFoundation/AVFoundation.h>

namespace jami { namespace video {

class VideoDeviceImpl {
    public:
        /**
         * @throw std::runtime_error
         */
        VideoDeviceImpl(const std::string& path);

        std::string id;
        std::string name;

        std::vector<std::string> getChannelList() const;
        std::vector<VideoSize> getSizeList(const std::string& channel) const;
        std::vector<VideoSize> getSizeList() const;
        std::vector<FrameRate> getRateList(const std::string& channel, VideoSize size) const;

        DeviceParams getDeviceParams() const;
        void setDeviceParams(const DeviceParams&);

    private:
        VideoSize extractSize(VideoSize) const;

        AVCaptureDevice* avDevice_;
        std::vector<VideoSize> available_sizes_;
        VideoSize current_size_;
        FrameRate rate_ {};
        std::map<VideoSize, std::vector<FrameRate>> available_rates_;
        FrameRate desktopFrameRate_ = {30};
        std::vector<FrameRate> desktopFrameRates_ = {FrameRate(5),
                                                     FrameRate(10),
                                                     FrameRate(15),
                                                     FrameRate(20),
                                                     FrameRate(25),
                                                     FrameRate(30),
                                                     FrameRate(60),
                                                     FrameRate(120),
                                                     FrameRate(144)};
};

VideoDeviceImpl::VideoDeviceImpl(const std::string& uniqueID)
    : id(uniqueID)
    , current_size_(-1, -1)
    , avDevice_([AVCaptureDevice deviceWithUniqueID:
        [NSString stringWithCString:uniqueID.c_str() encoding:[NSString defaultCStringEncoding]]])
{

    if (id == DEVICE_DESKTOP) {
          name = DEVICE_DESKTOP;
          VideoSize size {0, 0};
          available_sizes_.emplace_back(size);
          available_rates_[size] = desktopFrameRates_;
          return;
      }
    name = [[avDevice_ localizedName] UTF8String];

    available_sizes_.reserve(avDevice_.formats.count);
    for (AVCaptureDeviceFormat* format in avDevice_.formats) {
        auto dimensions = CMVideoFormatDescriptionGetDimensions(format.formatDescription);
        available_sizes_.emplace_back(dimensions.width, dimensions.height);
        std::vector<FrameRate> v;
        v.reserve(format.videoSupportedFrameRateRanges.count);
        for (AVFrameRateRange* frameRateRange in format.videoSupportedFrameRateRanges) {
            if(std::find(v.begin(), v.end(), frameRateRange.maxFrameRate) == v.end()) {
                v.emplace_back(frameRateRange.maxFrameRate);
            }
        }
        // if we have multiple formats with the same resolution use video supported framerates from last one
        // because this format will be selected by ffmpeg
        if (available_rates_.find( VideoSize(dimensions.width, dimensions.height) ) == available_rates_.end()) {
            available_rates_.emplace(VideoSize(dimensions.width, dimensions.height), v);
        } else {
            available_rates_.at(VideoSize(dimensions.width, dimensions.height)) = v;
        }
    }
}

VideoSize
VideoDeviceImpl::extractSize(VideoSize size) const
{
    for (const auto item : available_sizes_) {
        if (item.first == size.first && item.second == size.second)
            return item;
    }

    // fallback to last size
    if (!available_sizes_.empty()) {
        return available_sizes_.back();
    }
    return VideoSize(0, 0);
}

DeviceParams
VideoDeviceImpl::getDeviceParams() const
{
    DeviceParams params;
    params.unique_id = id;
    params.input = id;
    if (id == DEVICE_DESKTOP) {
        params.framerate = desktopFrameRate_;
        return params;
    }
    params.name = [[avDevice_ localizedName] UTF8String];
    params.framerate = rate_;
    params.format = "avfoundation";
    params.pixel_format = "nv12";
    params.width = current_size_.first;
    params.height = current_size_.second;
    return params;
}

void
VideoDeviceImpl::setDeviceParams(const DeviceParams& params)
{
    if (id == DEVICE_DESKTOP) {
        name = DEVICE_DESKTOP;
        desktopFrameRate_ = params.framerate;
        return;
    }
    rate_ = params.framerate;
    current_size_ = extractSize({params.width, params.height});
}

std::vector<VideoSize>
VideoDeviceImpl::getSizeList() const
{
    return getSizeList("default");
}

std::vector<FrameRate>
VideoDeviceImpl::getRateList(const std::string& channel, VideoSize size) const
{
    return available_rates_.at(size);
}

std::vector<VideoSize>
VideoDeviceImpl::getSizeList(const std::string& channel) const
{
    return available_sizes_;
}

std::vector<std::string>
VideoDeviceImpl::getChannelList() const
{
    return {"default"};
}

VideoDevice::VideoDevice(const std::string& path, const std::vector<std::map<std::string, std::string>>&) :
    deviceImpl_(new VideoDeviceImpl(path))
{
    id_ = path;
    name = deviceImpl_->name;
}

DeviceParams
VideoDevice::getDeviceParams() const
{
    return deviceImpl_->getDeviceParams();
}

void
VideoDevice::setDeviceParams(const DeviceParams& params)
{
    return deviceImpl_->setDeviceParams(params);
}

std::vector<std::string>
VideoDevice::getChannelList() const
{
    return deviceImpl_->getChannelList();
}

std::vector<VideoSize>
VideoDevice::getSizeList(const std::string& channel) const
{
    return deviceImpl_->getSizeList(channel);
}

std::vector<FrameRate>
VideoDevice::getRateList(const std::string& channel, VideoSize size) const
{
    return deviceImpl_->getRateList(channel, size);
}

VideoDevice::~VideoDevice()
{}

}} // namespace jami::video
