/*
 * @Description: 
 * @Version: 1.0
 * @Autor: lishengyin
 * @Date: 2022-04-02 14:19:21
 * @LastEditors: Your Name lishengyin@sz-sunwin.com
 * @LastEditTime: 2022-06-16 22:07:00
 */
#include "Sectorpower.hpp"
#include "Disposition.hpp"
#include "Inspector.hpp"
#include "ProcessingIt.hpp"

namespace ins
{

    /**
     * @description: 对象构造函数
     * @param {*}
     * @return {*}
     */    
    Sectorpower::Sectorpower(): Module("Sectorpower")
    {  
        Init();
    }

    /**
     * @description:获取ptr 
     * @param {*}
     * @return {*}
     */    
    std::shared_ptr<Sectorpower> Sectorpower::getPtr(){
        static std::shared_ptr<Sectorpower> m_Sectorpower = nullptr;
        if(m_Sectorpower==nullptr) m_Sectorpower = std::shared_ptr<Sectorpower>(new Sectorpower);
        return m_Sectorpower;
    } 

    /**
     * @description: 初始化
     * @param {*}
     * @return {*}
     */    
    int8_t Sectorpower::Init() {
        if(this->valid) return OK;
        for(int i = 0; i < 2; i++){
            workers.push_back(thread([this](){
                while (true)
                {
                    InsPacket::Ptr packet = nullptr;
                    {
                        std::unique_lock<std::mutex> lock(m_mutex);
                        condition.wait(lock, [this](){
                            return stop || !Transactions.empty();
                        });
                        if(stop && Transactions.empty()) return;
                        packet = Transactions.front();
                        Transactions.pop();
                    }
                    if(packet == nullptr) return;
                    // 获取工作流
                    ins::InsTask::Ptr task = this->getWorkflowTask(packet);
                    if(task == nullptr) return;
                    TaskCenter::Ptr m_TaskCenter = TaskCenter::CreateNew();
                    if(m_TaskCenter->enqueue(task) != OK){
                        WarnL << "Task into the team failed!" << endl;
                    }
                }
            }));
        }
        this->valid = true;
        return OK;
    }

    /**
     * @description: 释放资源
     * @param {*}
     * @return {*}
     */    
    void Sectorpower::Destroy() {
        {
            std::unique_lock<std::mutex> lock(m_mutex);
            stop = true;
        }
        condition.notify_all();
        for(auto &worker :workers)
        {
            worker.join();
        } 
    }

    /**
     * @description: 审查任务
     * @param {*}
     * @return {*}
     */    
    bool Sectorpower::reviewTask(ins::InsTask::Ptr& task){
        // todo 审批任务流程
        std::unique_lock<std::mutex> lock(m_mutex);
        
        return true;
    }
    
    /**
     * @description: 获取工作流任务
     * @param {Ptr&} pack
     * @return {*}
     */    
    InsTask::Ptr Sectorpower::getWorkflowTask(InsPacket::Ptr pack){
        std::unique_lock<std::mutex> lock(m_mutex);
        if(pack == nullptr) return nullptr;
        ins::InsTask::Ptr task = nullptr;
        switch (pack->getSourceType())
        {
        // 内部数据
        case InsPacketTypes::INS_ROUTINE_PACKET:
            task = ins::InsTask::CreateNew(InsTask::MakeTaskPtr([pack](){
                pack->setSqlResult(GetCenter::getPtr()->ExecuteSql(pack->getData()->data));
                if(pack->IsInsPackTask()){
                    (*pack->getInsPackTask())(pack);
                }
            }));
            break;
        default:
            // 常规的工作流
            task = ins::InsTask::CreateNew(InsTask::MakeTaskPtr([pack](){
                // 解析数据
                if(ProcessingIt::getPtr()->ParserData(pack)){
                    if(pack->getBournType() == InsPacketTypes::INS_MYSQL_PACKET){
                        if(pack->getToData()->format == InsDataFormat::INS_DATA_FORMAT_SQL) {
                            pack->setSqlResult(GetCenter::getPtr()->ExecuteSql(pack->getToData()->data));
                            // 后处理
                            GetCenter::getPtr()->ExecuteSql(pack->getToData()->attr2);
                        }
                        else WarnL << "The parsed data is not in line with the target requirements" << endl;
                    }
                    if(pack->IsInsPackTask()){
                        (*pack->getInsPackTask())(pack);
                    }
                }
            }));
            break;
        }
        return task;
    }
    
    /**
     * @description: 业务入队
     * @param {Ptr} packet
     * @return {*}
     */    
    int8_t Sectorpower::enqueue(InsPacket::Ptr packet){
        if(packet == nullptr) return ERR;
        {
            std::unique_lock<std::mutex> lock(m_mutex);
            if(stop) return ERR;
            Transactions.push(packet);
            condition.notify_one();
        }
        if(stop) return ERR;
        return OK;
    }

} // namespace ins
