/**
 *  Copyright (C) 2021 Savoir-faire Linux Inc.
 *
 *  Author: Aline Gondim Santos <aline.gondimsantos@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 "WatermarkVideoSubscriber.h"

extern "C" {
#include <libavutil/display.h>
}
#include <accel.h>
#include <frameScaler.h>
#include <common.h>

#include <pluglog.h>
#include <algorithm>
#include <ctime>
#include <clocale>
#include <iostream>

const std::string TAG = "Watermark";
const char sep = separator();

namespace jami {

WatermarkVideoSubscriber::WatermarkVideoSubscriber(const std::string& dataPath)
{
    if (std::setlocale(LC_TIME, std::locale("").name().c_str()) == NULL) {
        Plog::log(Plog::LogPriority::INFO, TAG, "error while setting locale");
    }

    std::setlocale(LC_NUMERIC, "C");
    fontFile_ = string_utils::ffmpegFormatString(dataPath + sep + "Muli-Light.ttf");
}

WatermarkVideoSubscriber::~WatermarkVideoSubscriber()
{
    validLogo_ = false;
    logoFilter_.clean();
    detach();
    std::lock_guard<std::mutex> lk(mtx_);
    Plog::log(Plog::LogPriority::INFO, TAG, "~WatermarkMediaProcessor");
}

MediaStream
WatermarkVideoSubscriber::getLogoAVFrameInfos()
{
    AVFormatContext* ctx = avformat_alloc_context();

    // Open
    if (avformat_open_input(&ctx, logoPath_.c_str(), NULL, NULL) != 0) {
        avformat_free_context(ctx);
        Plog::log(Plog::LogPriority::INFO, TAG, "Couldn't open input stream.");
        validLogo_ = false;
        return {};
    }
    pFormatCtx_.reset(ctx);
    // Retrieve stream information
    if (avformat_find_stream_info(pFormatCtx_.get(), NULL) < 0) {
        Plog::log(Plog::LogPriority::INFO, TAG, "Couldn't find stream information.");
        validLogo_ = false;
        return {};
    }

    // Dump valid information onto standard error
    av_dump_format(pFormatCtx_.get(), 0, logoPath_.c_str(), false);

    // Find the video stream
    for (int i = 0; i < static_cast<int>(pFormatCtx_->nb_streams); i++)
        if (pFormatCtx_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoStream_ = i;
            break;
        }

    if (videoStream_ == -1) {
        Plog::log(Plog::LogPriority::INFO, TAG, "Didn't find a video stream.");
        validLogo_ = false;
        return {};
    }

    rational<int> fr = pFormatCtx_->streams[videoStream_]->r_frame_rate;
    return MediaStream("logo",
                       pFormatCtx_->streams[videoStream_]->codecpar->format,
                       1 / fr,
                       pFormatCtx_->streams[videoStream_]->codecpar->width,
                       pFormatCtx_->streams[videoStream_]->codecpar->height,
                       0,
                       fr);
}

void
WatermarkVideoSubscriber::loadMarkLogo()
{
    if (logoPath_.empty())
        return;

    logoFilter_.clean();
    logoDescription_ = "[logo]scale=" + logoSize_ + "*" + std::to_string(pluginFrameSize_.first)
                       + ":" + logoSize_ + "*" + std::to_string(pluginFrameSize_.second)
                       + ":force_original_aspect_ratio='decrease',format=yuva444p,"
                         "split=2[bg][fg],[bg]drawbox=c='"
                       + backgroundColor_
                       + "':replace=1:t=fill[bg],"
                         "[bg][fg]overlay=format=auto";
    Plog::log(Plog::LogPriority::INFO, TAG, logoDescription_);
    logoStream_ = getLogoAVFrameInfos();
    logoFilter_.initialize(logoDescription_, {logoStream_});

    AVCodecContext* pCodecCtx;

    const AVCodec* pCodec = avcodec_find_decoder(
        pFormatCtx_->streams[videoStream_]->codecpar->codec_id);
    if (pCodec == nullptr) {
        pFormatCtx_.reset();
        Plog::log(Plog::LogPriority::INFO, TAG, "Codec not found.");
        validLogo_ = false;
        return;
    }

    pCodecCtx = avcodec_alloc_context3(pCodec);
    // Open codec
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
        pFormatCtx_.reset();
        Plog::log(Plog::LogPriority::INFO, TAG, "Could not open codec.");
        validLogo_ = false;
        return;
    }

    AVPacket* packet = av_packet_alloc();

    if (av_read_frame(pFormatCtx_.get(), packet) < 0) {
        avcodec_close(pCodecCtx);
        avcodec_free_context(&pCodecCtx);
        av_packet_unref(packet);
        av_packet_free(&packet);
        pFormatCtx_.reset();
        Plog::log(Plog::LogPriority::INFO, TAG, "Could not read packet from context.");
        validLogo_ = false;
        return;
    }

    if (avcodec_send_packet(pCodecCtx, packet) < 0) {
        avcodec_close(pCodecCtx);
        avcodec_free_context(&pCodecCtx);
        av_packet_unref(packet);
        av_packet_free(&packet);
        pFormatCtx_.reset();
        Plog::log(Plog::LogPriority::INFO, TAG, "Could not send packet no codec.");
        validLogo_ = false;
        return;
    }

    uniqueFramePtr logoImage = {av_frame_alloc(), frameFree};
    if (avcodec_receive_frame(pCodecCtx, logoImage.get()) < 0) {
        avcodec_close(pCodecCtx);
        avcodec_free_context(&pCodecCtx);
        av_packet_unref(packet);
        av_packet_free(&packet);
        pFormatCtx_.reset();
        Plog::log(Plog::LogPriority::INFO, TAG, "Could not read packet from codec.");
        validLogo_ = false;
        return;
    }

    logoFilter_.feedInput(logoImage.get(), "logo");
    logoFilter_.feedEOF("logo");

    avcodec_close(pCodecCtx);
    avcodec_free_context(&pCodecCtx);
    av_packet_unref(packet);
    av_packet_free(&packet);
    pFormatCtx_.reset();
    mark_.reset(logoFilter_.readOutput());
    mark_->pts = 0;
    mark_->best_effort_timestamp = 0;
    validLogo_ = mark_->width && mark_->height;
}

void
WatermarkVideoSubscriber::setParameter(std::string& parameter, Parameter type)
{
    switch (type) {
    case (Parameter::LOGOSIZE):
        logoSize_ = parameter;
        break;
    case (Parameter::TIMEZONE):
        timeZone_ = parameter == "1";
        return;
    case (Parameter::FONTSIZE):
        fontSize_ = std::stoi(parameter);
        break;
    case (Parameter::LOGOBACKGROUND):
        backgroundColor_ = parameter;
        if (backgroundColor_.find("black") == std::string::npos) {
            fontColor_ = "black";
            fontBackground_ = "white@0.5";
        } else {
            fontColor_ = "white";
            fontBackground_ = "black@0.5";
        }
        break;
    case (Parameter::SHOWLOGO):
        showLogo_ = parameter == "1";
        break;
    case (Parameter::SHOWINFOS):
        showInfos_ = parameter == "1";
        break;
    case (Parameter::LOGOPATH):
        logoPath_ = parameter;
        break;
    case (Parameter::TIME):
        time_ = parameter == "1";
        break;
    case (Parameter::DATE):
        date_ = parameter == "1";
        break;
    case (Parameter::TIMEFORMAT):
        timeFormat_ = "%{localtime\\:'" + parameter + "'}";
        if (timeZone_)
            timeFormat_ = "%{localtime\\:'" + parameter + " %Z'}";
        break;
    case (Parameter::DATEFORMAT):
        dateFormat_ = "%{localtime\\:'" + parameter + "'}";
        break;
    case (Parameter::LOCATION):
        location_ = parameter;
        break;
    case (Parameter::INFOSPOSITION):
        infosposition_ = parameter;
        break;
    case (Parameter::LOGOPOSITION):
        logoposition_ = parameter;
        break;
    default:
        return;
    }

    firstRun = true;
}

void
WatermarkVideoSubscriber::setFilterDescription()
{
    loadMarkLogo();

    std::string infoSep = ", ";
    if (pluginFrameSize_.first < pluginFrameSize_.second)
        infoSep = ",\n";

    std::vector<std::string> infos;
    infosSize_ = 0;
    if (!location_.empty()) {
        infosSize_++;
        infos.emplace_back(location_);
    }
    if (date_) {
        infosSize_++;
        infos.emplace_back(dateFormat_);
    }
    if (time_) {
        infosSize_++;
        infos.emplace_back(timeFormat_);
    }
    infosString.clear();
    for (int i = 0; i < infosSize_ - 1; i++)
        infosString += infos[i] + infoSep;
    if (infosSize_ > 0)
        infosString += infos.back();

    setMarkPosition();

    std::string rotateSides = "";
    if (std::abs(angle_) == 90)
        rotateSides = ":out_w=ih:out_h=iw";
    std::string formatedPath = string_utils::ffmpegFormatString(logoPath_);

    auto gifDescription = "movie='" + formatedPath + "':loop=0,setpts=N/(FR*TB)[logo],"
                          + logoDescription_ + "[loop],";

    if (angle_ != 0)
        pluginFilterDescription_ = gifDescription
                                   + "[input]rotate=" + rotation[angle_] + rotateSides
                                   + "[rot],[rot][loop]overlay=" + std::to_string(points_[0].first)
                                   + ":" + std::to_string(points_[0].second)
                                   + ",rotate=" + rotation[-angle_] + rotateSides;
    else
        pluginFilterDescription_ = gifDescription
                                   + "[input][loop]overlay="
                                   + std::to_string(points_[0].first) + ":"
                                   + std::to_string(points_[0].second);

    std::string baseInfosDescription = "[input]rotate=" + rotation[angle_] + rotateSides
                                       + ",drawtext=fontfile='" + fontFile_ + "':text='"
                                       + infosString + "':fontcolor=" + fontColor_
                                       + ":fontsize=" + std::to_string(fontSize_)
                                       + ":line_spacing=" + std::to_string(lineSpacing_)
                                       + ":box=1:boxcolor=" + fontBackground_ + ":boxborderw=5:x=";

    if (infosposition_ == "1")
        infosDescription_ = baseInfosDescription + std::to_string(points_[1].first)
                            + "-text_w:y=" + std::to_string(points_[1].second);
    else if (infosposition_ == "2")
        infosDescription_ = baseInfosDescription + std::to_string(points_[1].first)
                            + ":y=" + std::to_string(points_[1].second);
    else if (infosposition_ == "3")
        infosDescription_ = baseInfosDescription + std::to_string(points_[1].first)
                            + ":y=" + std::to_string(points_[1].second) + "-text_h";
    else if (infosposition_ == "4")
        infosDescription_ = baseInfosDescription + std::to_string(points_[1].first)
                            + "-text_w:y=" + std::to_string(points_[1].second) + "-text_h";
    infosDescription_ += ",rotate=" + rotation[-angle_] + rotateSides + ",format=yuv420p";

    Plog::log(Plog::LogPriority::INFO, TAG, infosDescription_);
    Plog::log(Plog::LogPriority::INFO, TAG, pluginFilterDescription_);
}

void
WatermarkVideoSubscriber::setMarkPosition()
{
    if (!validLogo_)
        return;
    // 1, 2, 3, and 4 are cartesian positions
    int margin = 10;
    int markWidth = showLogo_ ? mark_->width : 0;
    int markHeight = showLogo_ ? mark_->height : 0;
    int infoHeight = (std::abs(angle_) == 90) ? (fontSize_ + lineSpacing_) * infosSize_
                                              : lineSpacing_ * 2 + fontSize_;
    if (pluginFrameSize_.first == 0 || pluginFrameSize_.second == 0)
        return;

    if (infosposition_ == "1") {
        points_[1] = {pluginFrameSize_.first - margin, margin};
    } else if (infosposition_ == "2") {
        points_[1] = {margin, margin};
    } else if (infosposition_ == "3") {
        points_[1] = {margin, pluginFrameSize_.second - margin};
    } else if (infosposition_ == "4") {
        points_[1] = {pluginFrameSize_.first - margin, pluginFrameSize_.second - margin};
    }
    if (logoposition_ == "1") {
        points_[0] = {pluginFrameSize_.first - mark_->width - margin / 2, margin};
    } else if (logoposition_ == "2") {
        points_[0] = {margin / 2, margin};
    } else if (logoposition_ == "3") {
        points_[0] = {margin / 2, pluginFrameSize_.second - markHeight - margin};
    } else if (logoposition_ == "4") {
        points_[0] = {pluginFrameSize_.first - markWidth - margin / 2,
                      pluginFrameSize_.second - markHeight - margin};
    }

    if (infosposition_ == logoposition_ && showInfos_ && showLogo_) {
        if (logoposition_ == "1" || logoposition_ == "2") {
            points_[0].second += infoHeight;
        } else if (logoposition_ == "3" || logoposition_ == "4") {
            points_[0].second -= infoHeight;
        }
    }
}

void
WatermarkVideoSubscriber::update(jami::Observable<AVFrame*>*, AVFrame* const& pluginFrame)
{
    if (!observable_ || !pluginFrame || (showLogo_ && !validLogo_))
        return;

    AVFrameSideData* side_data = av_frame_get_side_data(pluginFrame, AV_FRAME_DATA_DISPLAYMATRIX);
    int newAngle {0};
    if (side_data) {
        auto matrix_rotation = reinterpret_cast<int32_t*>(side_data->data);
        newAngle = static_cast<int>(av_display_rotation_get(matrix_rotation));
    }
    if (newAngle != angle_) {
        angle_ = newAngle;
        firstRun = true;
    }

    //======================================================================================
    // GET RAW FRAME
    uniqueFramePtr rgbFrame = {transferToMainMemory(pluginFrame, AV_PIX_FMT_NV12), frameFree};
    rgbFrame.reset(FrameScaler::convertFormat(rgbFrame.get(), AV_PIX_FMT_YUV420P));
    if (!rgbFrame.get())
        return;

    if (sourceTimeBase_.num != pluginFrame->time_base.num || sourceTimeBase_.den != pluginFrame->time_base.den)
        firstRun = true;

    rgbFrame->pts = pluginFrame->pts;
    rgbFrame->time_base = pluginFrame->time_base;
    sourceTimeBase_ = pluginFrame->time_base;

    if (firstRun) {
        pluginFilter_.clean();
        infosFilter_.clean();
        pluginFrameSize_ = {rgbFrame->width, rgbFrame->height};
        if (std::abs(angle_) == 90)
            pluginFrameSize_ = {rgbFrame->height, rgbFrame->width};

        setFilterDescription();

        rational<int> fr(sourceTimeBase_.den, sourceTimeBase_.num);
        pluginstream_ = MediaStream("input",
                                    rgbFrame->format,
                                    1 / fr,
                                    rgbFrame->width,
                                    rgbFrame->height,
                                    0,
                                    fr);

        if (showLogo_ && validLogo_) {
            pluginFilter_.initialize(pluginFilterDescription_, {pluginstream_});
        }

        infosFilter_.initialize(infosDescription_, {pluginstream_});
        firstRun = false;
    }

    if (!infosFilter_.initialized_ && !pluginFilter_.initialized_)
        return;

    if (showLogo_ && validLogo_) {
        if (pluginFilter_.feedInput(rgbFrame.get(), "input") == 0) {
            uniqueFramePtr filteredFrame = {pluginFilter_.readOutput(), frameFree};
            if (filteredFrame.get())
                moveFrom(rgbFrame.get(), filteredFrame.get());
        }
    }
    if (showInfos_) {
        if (infosFilter_.feedInput(rgbFrame.get(), "input") == 0) {
            uniqueFramePtr filteredFrame = {infosFilter_.readOutput(), frameFree};
            if (filteredFrame.get())
                moveFrom(rgbFrame.get(), filteredFrame.get());
        }
    }
    if (showInfos_ || showLogo_) {
        moveFrom(pluginFrame, rgbFrame.get());
    }
}

void
WatermarkVideoSubscriber::attached(jami::Observable<AVFrame*>* observable)
{
    Plog::log(Plog::LogPriority::INFO, TAG, "Attached!");
    observable_ = observable;
}

void
WatermarkVideoSubscriber::detached(jami::Observable<AVFrame*>*)
{
    pluginFilter_.clean();
    infosFilter_.clean();
    firstRun = true;
    observable_ = nullptr;
    Plog::log(Plog::LogPriority::INFO, TAG, "Detached!");
    mtx_.unlock();
}

void
WatermarkVideoSubscriber::detach()
{
    if (observable_) {
        mtx_.lock();
        firstRun = true;
        observable_->detach(this);
    }
}
} // namespace jami
