#include "main.h"
#include "BoostLog.h"
#include "FFmpegResample.h"
#include "IoContext.h"
#include "WebRTCPublisher.h"
#include <boost/asio/signal_set.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>
#include <com/amazonaws/kinesis/video/webrtcclient/Include.h>
#include <filesystem>
#include <fstream>
#ifdef __RV1109__
#include <rkmedia/rkmedia_api.h>
#endif

void signal_handler(const boost::system::error_code &error, int signal_number) {
    if (!error) {
        LOG(info) << "Caught signal: " << signal_number << std::endl;

        LOG(info) << "task finished.";
        std::exit(0);
    }
}

int main(int argc, char **argv) {
    using namespace Amass;
    using namespace std::placeholders;
    boost::program_options::options_description optionsDescription("Allowed options");
    // clang-format off
    optionsDescription.add_options()
        ("help,h", "produce help message")
        ("echo", "Self-recording and self-play test")
        ("record", "Record to file.")
        ("play", "Play pcm file.")
        ("file", "process file.")
        ("dsp", boost::program_options::value<std::string>()->default_value("aecm"), "vqe, speex, aecm")
        ("channels", boost::program_options::value<int>(), "set audio channles")
        ("path", boost::program_options::value<std::string>(), "file path")
        ("dump,d", boost::program_options::value<bool>()->default_value(false), "dump file.")
    ;
    // clang-format on

    boost::program_options::variables_map variablesMap;
    boost::program_options::store(boost::program_options::parse_command_line(argc, argv, optionsDescription), variablesMap);
    boost::program_options::notify(variablesMap);

    if (variablesMap.count("help")) {
        std::cout << optionsDescription << std::endl;
        return 1;
    }

    std::shared_ptr<Task> task;
    if (variablesMap.count("echo")) {
        int channels = 2;
        if (variablesMap.count("channels")) {
            channels = variablesMap["channels"].as<int>();
        }
#ifdef __RV1109__
        auto t = std::make_shared<EchoRecordTask>();
        t->setDsp(dspFromString(variablesMap["dsp"].as<std::string>()));
        t->setChannels(channels);
        t->setDumpEnabled(variablesMap["dump"].as<bool>());
        task = std::dynamic_pointer_cast<Task>(t);
#endif
    } else if (variablesMap.count("record")) {
#ifdef __RV1109__
        task = std::make_shared<RecorderTask>();
#endif
    } else if (variablesMap.count("play")) {
        std::string path;
        if (variablesMap.count("path")) {
            path = variablesMap["path"].as<std::string>();
        }

        int channels = 2;
        if (variablesMap.count("channels")) {
            channels = variablesMap["channels"].as<int>();
        }
#ifdef __RV1109__
        auto t = std::make_shared<PlayerTask>();
        t->setChannels(channels);
        t->setPath(path);
        task = std::dynamic_pointer_cast<Task>(t);
#endif
    } else if (variablesMap.count("file")) {
        auto t = std::make_shared<ProcessFileTask>();
        t->setDsp(dspFromString(variablesMap["dsp"].as<std::string>()));
        task = std::dynamic_pointer_cast<Task>(t);
    }

    if (!task) {
        std::cout << "there is not task." << std::endl << std::endl;
        std::cout << optionsDescription << std::endl;
        return 2;
    }
    if (!std::filesystem::exists(DumpPath)) {
        std::filesystem::create_directory(DumpPath);
    }

    try {
        LOG(info) << "app start.";
#ifdef __RV1109__
        RK_MPI_SYS_Init();
#endif
        initKvsWebRtc();
        auto ioConext = Singleton<IoContext>::instance<Construct>();
        boost::asio::signal_set signals(*ioConext->ioContext(), SIGINT, SIGTERM);
        signals.async_wait(std::bind(&signal_handler, _1, _2));

        task->run();

        ioConext->run<IoContext::Mode::Synchronous>();
    } catch (std::exception &e) {
        LOG(error) << "Exception: " << e.what() << std::endl;
    }

    // WebRTCPublisher publisher(true, true);
    // publisher.start("172.16.103.68", "443", "/index/api/webrtc?app=live&stream=test&type=push");
    return 0;
}

Dsp dspFromString(const std::string &dsp) {
    Dsp ret = Vqe;
    if (dsp == "speex") {
        ret = Speex;
    } else if (dsp == "aecm") {
        ret = AecMobile;
    } else if (dsp == "aec3") {
        ret = Aec3;
    }
    return ret;
}

std::string dspToString(Dsp dsp) {
    std::string ret = "none";
    if (dsp == Vqe) {
        ret = "vqe";
    } else if (dsp == Speex) {
        ret = "speex";
    } else if (dsp == AecMobile) {
        ret = "aecm";
    } else if (dsp == Aec3) {
        ret = "aec3";
    }
    return ret;
}