package com.base.task.core;

import com.base.task.TaskInitialize;
import com.base.task.core.listener.FileMonitor;
import com.base.task.model.Enums.TaskTypeEnum;
import com.base.task.model.Task;
import com.base.task.model.TaskPreparations;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class Execute {

    private Map<TaskTypeEnum, Thread> threadMap = new HashMap<>();

    @Resource
    TaskInitialize taskInitialize;
    @Resource
    TaskPreparations taskPreparations;

    public void addThread(TaskTypeEnum type, Thread thread) {
        threadMap.put(type,thread);
    }

    public void start() {
        for (Map.Entry<TaskTypeEnum, Thread> entry : threadMap.entrySet()) {
            entry.getValue().start();
            log.info(entry.getValue().getName() + " start success!!!");

        }
    }

    /**
     * 查询
     */
    public void checkExecuteQueue() {
        TaskCache taskCache = TaskCache.getInstance();
        if (taskCache.getQueueTaskNumber() == 0) {
            return;
        }
        for (Task task : taskCache.getTasks()) {
            if (taskCache.getTypeCurrentNum(task.getTaskType()) >= taskPreparations.getExePackageCounts()) {
                log.error(task.getTaskType().toString() + " task is full!!!");
                continue;
            }
            Task task1 = new Task();
            BeanUtils.copyProperties(task, task1);
            taskCache.addCurrentTask(task1);
            taskCache.removeTask(task.getTaskSerial());
        }
    }

    public void execute(Task task) {
        try {

            //写配置文件
            log.info("===============写配置文件=============");
            boolean writeInputRes = writeInput(task);
            if (writeInputRes) {
                log.info("===============写配置文件成功=============");
                log.info("input write success!!!");
                log.info("===============查询是否有ok文件有删除=============");
                if (deleteOldOkFile(task.getOkFilePath()+task.getOkFileName())) {
                    log.info("===============ok文件判断删除成功=============");
                    File fileOk=new File(task.getOkFilePath()+task.getOkFileName());
                    if (fileOk.exists()){
                        fileOk.delete();
                    }
                    //新增监听器
                    log.info("===============新增监听器=============");
                    setListener(task);
                    task.setState(1);
                    log.info("===============开始调用exe文件=============");
                    log.info("===============exe文件路径============="+task.getExeFilePath()+task.getExeFileName()+"==============");
                    Process exec = Runtime.getRuntime().exec(task.getExeFilePath()+task.getExeFileName(), null, new File( task.getExeFilePath()));
                    log.info("===============调用exe文件完成=============");
                    task.setProcess(exec);
                } else {
                    log.error("delete okFile fail!!!");
                    task.getCountDownLatch().countDown();
                }
            } else {
                log.error("input write fail!!!");
                task.getCountDownLatch().countDown();
            }
        } catch (Exception e) {
            log.error("execute task error!!!",e);
            task.getCountDownLatch().countDown();
        }finally {
            //改变任务状态
            task.setState(1);
        }

    }

    private boolean deleteOldOkFile(String okFile) {
        File oldOkFile = new File(okFile);
        if (!oldOkFile.exists()){
            return true;
        }else {
            return oldOkFile.delete();
        }

    }

    private void setListener(Task task) {
        FileMonitor.getInstance().addListener(task);
    }

    public boolean writeInput(Task task) {
        String data = taskUtils.getTaskInputString(task.getInput().getClass(), task.getInput());
        task.getInput().setDataInput(data);
        return taskInitialize.map.get(task.getTaskType()).input(task.getInput(), task.getInpPath(),task.getInpName());
    }


}
