/**
 * @file sched_example.cpp
 * @brief 工位预约对应sdk示例
 *
 * @copyright Copyright (C) 2024 ROKAE (Beijing) Technology Co., LTD. All Rights Reserved.
 * Information in this file is the intellectual property of Rokae Technology Co., Ltd,
 * And may contains trade secrets that must be stored and viewed confidentially.
 */

#include "print_helper.hpp"
#include "rokae/arcwelding.h"
#include "rokae/data_types.h"
#include "rokae/robot.h"
#include <chrono>
#include <future>
#include <iostream>
#include <thread>
#include <unordered_map>

using namespace rokae;
using namespace std;

int main() {
  try {
    string ip = "192.168.110.129";
    xMateRobot robot(ip);
    error_code ec;
    /********************* 设置回调/监视 *********************/
    auto printSchedInfo = [](const EventInfo info) {
      using namespace EventInfoKey::SchedState;
      auto enable = std::any_cast<bool>(info.at(Enable));
      auto registerEnable = std::any_cast<bool>(info.at(RegisterEnable));
      auto schedState = std::any_cast<std::vector<SchedStatus>>(info.at(Status));
      cout << "call back" << endl;
      cout << Enable << ": " << enable << endl;
      cout << RegisterEnable << ": " << registerEnable << endl;
      cout << Status << ": " << endl;
      for (const auto &item : schedState) {
        cout << "id: " << item.id << endl
             << "state: " << item.state << " rank: " << item.rank << " count: " << item.count << endl;
      }
    };
    robot.setEventWatcher(Event::schedState, printSchedInfo, ec);
    cout << "setEventWatcher: " << ec.message() << endl;

    /********************* 启用/停用预约 *********************/
    bool enable = true;
    bool enableStatus;
    robot.enableSched(enable, ec);
    cout << "enable sched: " << ec.message() << endl;
    enableStatus = robot.getSchedEnableStatus(ec);
    cout << "getSchedEnableStatus: " << ec.message() << endl;
    cout << "sched enable status: " << enableStatus << endl;

    enable = false;
    robot.enableSched(enable, ec);
    cout << "enable sched: " << ec.message() << endl;
    enableStatus = robot.getSchedEnableStatus(ec);
    cout << "getSchedEnableStatus: " << ec.message() << endl;
    cout << "sched enable status: " << enableStatus << endl;

    /********************* 开始/停止预约 *********************/
    // 需要在启用预约，自动模式，上电之后才能开始预约
    robot.enableSched(true, ec);
    robot.setOperateMode(OperateMode::automatic, ec);
    robot.setPowerState(true, ec);

    bool registerEnable = true;// 开始预约
    bool registerEnableStatus;
    robot.registerEnableSched(registerEnable, ec);
    cout << "registerEnableSched: " << ec.message() << endl;
    registerEnableStatus = robot.getSchedRegisterEnableStatus(ec);
    cout << "getSchedRegisterEnableStatus: " << ec.message() << endl;
    cout << "sched register enable status: " << registerEnableStatus << endl;

    registerEnable = false;// 停止预约
    robot.registerEnableSched(registerEnable, ec);
    cout << "registerEnableSched: " << ec.message() << endl;
    registerEnableStatus = robot.getSchedRegisterEnableStatus(ec);
    cout << "getSchedRegisterEnableStatus: " << ec.message() << endl;
    cout << "sched register enable status: " << registerEnableStatus << endl;

    /*********************** 预约设置 ************************/
    // 可以使用projectsInfo获取控制器工程信息
    auto projInfo = robot.projectsInfo(ec);
    for (const auto &info : projInfo) {
      cout << "project name: " << info.name << endl;
    }

    SchedSetting schedSettingReturn;
    auto printSched = [](const SchedSetting &schedSetting) {
      for (const auto &item : schedSetting.schedEntrys) {
        cout << "id: " << item.id << endl;
        cout << "enable: " << item.enable << " name: " << item.name << " count: " << item.count << endl;
        cout << "register type: " << item.register_binding.type << " register name: " << item.register_binding.name << endl;
        cout << "register_cancel type: " << item.register_cancel.type << " register_cancel name: " << item.register_cancel.name << endl;
        cout << "register_status type: " << item.register_status.type << " register_status name: " << item.register_status.name << endl;
      }
    };

    SchedSetting schedSetting;
    schedSetting.get(2).enable = true;
    schedSetting.get(2).name = projInfo[0].name;
    schedSetting.get(2).count = 3;
    schedSetting.get(2).register_binding.type = "DI";
    schedSetting.get(2).register_binding.name = "DI0_0";
    schedSetting.get(2).register_cancel.type = "DI";
    schedSetting.get(2).register_cancel.name = "DI0_1";
    schedSetting.get(2).register_status.type = "DO";
    schedSetting.get(2).register_status.name = "DO0_0";
    robot.setSched(schedSetting, ec);// 设置
    cout << "setSched: " << ec.message() << endl;
    schedSettingReturn = robot.getSchedSetting(ec);// 获取设置
    cout << "getSchedSetting: " << ec.message() << endl;
    printSched(schedSettingReturn);

    /********************** 预约/取消预约 ***********************/
    // 需要在开始预约之后才能预约
    robot.enableSched(true, ec);
    robot.setOperateMode(OperateMode::automatic, ec);
    robot.setPowerState(true, ec);
    robot.registerEnableSched(true, ec);

    std::vector<SchedStatus> schedStatus;// 预约状态
    auto printSchedStatus = [](const std::vector<SchedStatus> &schedStatus) {
      for (const auto &item : schedStatus) {
        cout << "id: " << item.id << endl
             << "state: " << item.state << " rank: " << item.rank << " count: " << item.count << endl;
      }
    };

    robot.registerSched(2, ec);// 预约
    cout << "registerSched: " << ec.message() << endl;
    schedStatus = robot.getSchedStatus(ec);// 获取预约状态
    cout << "getSchedStatus: " << ec.message() << endl;
    printSchedStatus(schedStatus);

    robot.unregisterSched(2, ec);// 取消预约
    cout << "unregisterSched: " << ec.message() << endl;
    schedStatus = robot.getSchedStatus(ec);// 获取预约状态
    cout << "getSchedStatus: " << ec.message() << endl;
    printSchedStatus(schedStatus);

    robot.unregisterAllSched(ec);// 取消所有预约
    cout << "unregisterAllSched: " << ec.message() << endl;

    robot.clearSchedCount(ec);// 清除累计预约计数
    cout << "clearSchedCount: " << ec.message() << endl;

    robot.schedAdvancedSetting("pause_project", ec);
    cout << "schedAdvancedSetting: " << ec.message() << endl;
    robot.schedAdvancedSetting("unregister", ec);
    cout << "schedAdvancedSetting: " << ec.message() << endl;

  } catch (const std::exception &e) {
    std::cerr << e.what() << '\n';
  }
}