package com.example.fuzzControll.aop;

import com.example.fuzzControll.annotion.NeedCutBefore;
import com.example.fuzzControll.constents.CmdConstent;
import com.example.fuzzControll.constents.MissionStateEnum;
import com.example.fuzzControll.constents.TableClassEnum;
import com.example.fuzzControll.domain.po.MissionInfo;
import com.example.fuzzControll.exception.mysqlException.MysqlException;
import com.example.fuzzControll.exception.testException.AflnetException;
import com.example.fuzzControll.exception.testException.CmdException;
import com.example.fuzzControll.tools.system.GlobalClass;
import com.example.fuzzControll.tools.system.SystemRunningParams;
import com.example.fuzzControll.tools.test.SingleCmdTools;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import static com.example.fuzzControll.tools.system.GlobalClass.aflnetPersistenceService;


@Aspect
@Component
@Slf4j
public class beforeAop implements Ordered{
    SingleCmdTools singleCmdTools = new SingleCmdTools();

    @Pointcut(value = "@annotation(com.example.fuzzControll.annotion.NeedCutBefore)||@within(com.example.fuzzControll.annotion.NeedCutBefore)")
    private void beforeCut() {
    }


    /**
     * 用于aflnet测试相关的数据库操作
     */
    @Before("beforeCut()")
    private void before(JoinPoint point) {
        /*负责获取反射对象*/
        Signature signature = point.getSignature();
        MethodSignature methodSignature = null;
        if (!(signature instanceof MethodSignature)) {
            throw new IllegalArgumentException("该注解只能用于方法");
        }
        methodSignature = (MethodSignature) signature;
        Object target = point.getTarget();
        Method currentMethod = null;
        try {
            currentMethod = target.getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
        } catch (NoSuchMethodException e) {
            log.error("NoSuchMethod!");
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        NeedCutBefore logotype = currentMethod.getAnnotation(NeedCutBefore.class);
        /*aflnet相关处理逻辑,负责数据存入*/
        switch (logotype.name()) {
            case "aflnet":
                aflnet(logotype.function());
                break;
            case "kitty":
//                kitty(logotype.function());
                break;
            default:
                throw new AflnetException("Cut error: There is no name of anotation!");
        }
    }


    private void aflnet(String function) {
        if (function == null || "".equals(function)) {
            throw new AflnetException("There is no value in function!");
        }
        if ("startBackup".equals(function)) {
            /*存入alfnet启动时的任务信息*/
            try {
                int missionId = GlobalClass.missionInfoMapper.selectTopMissionId() + 1;
                SystemRunningParams.aflnetMissionId = missionId;
                GlobalClass.missionInfoMapper.insertMission(new MissionInfo(missionId, TableClassEnum.AFLNET.getTableId(), new Date(), SystemRunningParams.aflnetData.get("missionName"),
                        MissionStateEnum.RUNNING.getStateCode(), 0L));
            } catch (Exception e) {
                e.printStackTrace();
                throw new MysqlException("Aflnet start backup failed!");
            }
        } else if ("stopBackup".equals(function)) {
            /*存入alfnet停止时的任务信息*/
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        int flag = 0;
                        /*压缩aflnet产生的测试文件,为存入数据库做准备*/
                        String fileName = SystemRunningParams.aflnetData.get("aflnetName");
                        String fileZipName = fileName + ".zip";
                        singleCmdTools.runCmd(CmdConstent.RUN_ZIP_FILE + fileZipName + " " + fileName, "zip file in testStart");
                        List<String> files = singleCmdTools.runCmd(CmdConstent.GET_FILE_NAME + GlobalClass.aflnetProperties.getOutputPath(), "getSeedFiles");
                        if (!files.contains(fileZipName)) {
                            log.error("File zip error!");
                        }
                        /*存入压缩包*/
                        while (files.contains(fileZipName) && flag == 0) {//当前存在压缩包,且没有存过才存入,循环是等待压缩完成 todo 感觉这里后期会出现问题
                            flag = aflnetPersistenceService.aflnetResultBackup(fileZipName, MissionStateEnum.DONE.getStateCode(),
                                    SystemRunningParams.testTimeMessage.get("aflnet").get("end") - SystemRunningParams.testTimeMessage.get("aflnet").get("start"));
                        }
                        /*清除生成的文件*/
                        try {
                            singleCmdTools.runCmd(CmdConstent.DELETE_FILE + fileName, "delete file");
                            singleCmdTools.runCmd(CmdConstent.DELETE_FILE + fileZipName, "delete zipFile");
                        } catch (CmdException e) {
                            e.printStackTrace();
                            log.error("file delete failed!");
                        }

                        log.info("Aflnet Logs has been backuped!");
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw new MysqlException("Aflnet after backup failed!");
                    }
                }
            }).start();
        }
    }




    @Override
    public int getOrder() {
        return 1;
    }
}