//=============================================================================================================================
//
// Copyright (c) 2015-2022 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//=============================================================================================================================

#include "easyar/types.hpp"

#include <cmath>
#include <string>
#include <algorithm>
#include <memory>
#include <vector>
#include <unordered_map>
#include <cstdio>
#include <time.h>
#include <iostream>
#include <chrono>
#include <thread>
#include <functional>
#include <mutex>
#include <condition_variable>

std::shared_ptr<easyar::ImmediateCallbackScheduler> scheduler;

void loadFromImage(std::shared_ptr<easyar::ImageTracker> tracker, const std::string & path, const std::string & name, std::function<void(bool)> onCompleted)
{
    auto imageTarget = easyar::ImageTarget::createFromImageFile(path, easyar::StorageType::Assets, name, "", "", 1.0f);
    if (imageTarget.has_value())
    {
        tracker->loadTarget(imageTarget.value(), scheduler, [=](std::shared_ptr<easyar::Target> target, bool status)
        {
            std::printf("load target (%d): %s (%d)\n", status, target->name().c_str(), target->runtimeID());
            onCompleted(status);
        });
    }
    else
    {
        onCompleted(false);
    }
}

int main(int argc, char **argv)
{

    std::string saveDir = argc == 2 ? argv[1] : "";

    // initialize
    auto result = easyar::Engine::initialize("===PLEASE ENTER YOUR KEY HERE===");
    if (!result)
    {
        std::printf("Initialization failed.\n");
        return 1;
    }
    if (!easyar::CameraDevice::isAvailable())
    {
        std::printf("CameraDevice not available.\n");
        return 1;
    }
    if (!easyar::ImageTracker::isAvailable())
    {
        std::printf("ImageTracker not available.\n");
        return 1;
    }

    scheduler = easyar::ImmediateCallbackScheduler::getDefault();

    // load image with its name
    auto tracker = easyar::ImageTracker::createWithMode(easyar::ImageTrackerMode::PreferPerformance);

    auto totalImageCount = 2;

    std::mutex mutexCompletedCount;
    std::condition_variable conditionCompletedCount;
    auto completedCount = 0;

    auto onCompleted = [&](bool status)
    {
        {
            std::unique_lock<std::mutex> lock(mutexCompletedCount);
            completedCount += 1;
        }
        conditionCompletedCount.notify_one();
    };
    loadFromImage(tracker, "idback.jpg", "idback", onCompleted);
    loadFromImage(tracker, "namecard.jpg", "namecard", onCompleted);

    while (true)
    {
        std::unique_lock<std::mutex> lock(mutexCompletedCount);
        if (completedCount >= totalImageCount) { break; }
        conditionCompletedCount.wait(lock);
    }

    // save the image target data to file
    auto targets = tracker->targets();
    for (auto && target : targets) {
        auto imagetarget = std::dynamic_pointer_cast<easyar::ImageTarget>(target);
        // note: extension must be ".etd"
        auto path = saveDir + imagetarget->name() + ".etd";
        auto status = imagetarget->save(path);
        std::printf("save target: %s (%d) %s in \"%s\" directory\n", imagetarget->name().c_str(), imagetarget->runtimeID(),
                    status ? "success" : "fail", saveDir.empty() ? "project Debug|Release" : saveDir.c_str());
    }

    tracker = nullptr;

    scheduler = nullptr;

    return 0;
}
