package io.renren.modules.kubesphere.controller;

import com.alibaba.fastjson.JSON;
import com.google.gson.JsonObject;
import com.jcraft.jsch.JSchException;
import io.renren.common.utils.*;
import io.renren.modules.generator.entity.*;
import io.renren.modules.generator.service.*;
import io.renren.modules.kubesphere.service.ApplicationService;
import io.renren.modules.kubesphere.service.KubeSphereAlgorithmService;
import io.renren.modules.kubesphere.service.S2iService;
import io.renren.modules.kubesphere.service.impl.ImageServiceImpl;
import io.renren.modules.minio.service.impl.MinioAlgorithmServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.awt.*;
import java.io.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @Description
 * @Author chenrj.xdu@gmail.com
 * @Version V1.0.0
 * @Since 1.0
 * @Date 2021/10/11
 */

@RestController
@RequestMapping("kubeSphere")
public class KubeSphereAlgorithmController {
    //获取Dockerfile和shell脚本暂存地址
    @Value("${tempFileLocation}")
    private String tempFileLocation;

    @Value("${harborUrl}")
    private String harborUrl;

    private File packFile = null;
    @Autowired
    KubeSphereAlgorithmService algorithmService;

    @Autowired
    S2iService s2iService;

    @Autowired
    ApplicationService applicationService;

    @Autowired
    private ImagesService imagesService;

    @Autowired
    MinioAlgorithmServiceImpl minioAlgorithmService;

    @Autowired
    ImagesLogService imagesLogService;

    @Autowired
    VisiAlgNodeService visiAlgNodeService;

    @Autowired
    AlgorithmParameterService algorithmParameterService;

    @Autowired
    AlgorithmResultService algorithmResultService;

    @Autowired
    ModelService modelService;
    /**
     * 算法发布，即算法获取，打包，制作镜像
     *
     * @param jsonData
     * @return
     */
    @PostMapping("algorithmPublished")
    public R algorithmPublished(@RequestBody String jsonData) throws IOException, JSchException {
        String userName=ShiroUtils.getUserEntity().getUsername();

        System.out.println("当前操作用户名为"+userName);
        JsonObject jsonObject = GsonUtil.convertJsonObject(jsonData);
        //获取算法具体名称
        String algorithmName = jsonObject.get("algorithmName").getAsString();
        //获取model+id
        String modelName = minioAlgorithmService.findModelByName(algorithmName);
        //获取算法应用运行文件
        String appFile = minioAlgorithmService.findAppFileByName(algorithmName);
        //下载算法文件到服务器指定路径，下载前要将镜像构建信息改为算法下载中
        ModelEntity modelEntity=new ModelEntity();
        modelEntity.setModelId(Long.parseLong(modelName.substring(5)));
        modelEntity.setConstructMessage("算法下载中");
        modelService.updateConstructMessage(modelEntity);
        algorithmService.algorithmDownloadToServer(modelName);
        MyWebSocket.sendMessage("下载完成");
        //下载完成后将镜像构建信息改为镜像制作中
        modelEntity.setConstructMessage("镜像制作中");
        modelService.updateConstructMessage(modelEntity);
        String DockerfileShell = "FROM "+harborUrl+"/library/python3_base:v1.0\n" +
                "ENV CONFIG /\n" +
                "COPY ./" + "%s" + " $CONFIG\n" +
                "CMD [\"python\", \"" + "%s" + "\"]";
        //String[] shellArgs = {modelName, algorithmName, modelName};
        String[] shellArgs = {modelName, appFile, modelName};
        String DockerfilePath = tempFileLocation+"/Dockerfile";
        JavaShellUtil.generate(DockerfileShell, shellArgs, DockerfilePath);
        String buildShell = "#!/bin/bash\n" +
                "cd /home/mkcloud/algorithm\n" +
                "docker build -t " + " "+harborUrl+"/library/" + algorithmName + " .\n" +
                "docker push "+harborUrl+"/library/" + algorithmName;
        shellArgs = new String[]{modelName, modelName, modelName, modelName};
        String buildShellPath = tempFileLocation+"/buildShell.sh";
        JavaShellUtil.generate(buildShell, shellArgs, buildShellPath);
        String command = "sh /home/mkcloud/algorithm/buildShell.sh";
        File Dockerfile=new File(tempFileLocation+"/Dockerfile");
        File buildShellSh=new File(tempFileLocation+"/buildShell.sh");
        FTPUtils.uploadFile(".","Dockerfile",new FileInputStream(Dockerfile));
        FTPUtils.uploadFile(".","buildShell.sh",new FileInputStream(buildShellSh));
        //执行构建镜像命令，同时将构建日志存入数据库
        String exec=FTPUtils.execCmd(command);
        ImagesLogEntity imagesLogEntity=new ImagesLogEntity();
        imagesLogEntity.setModelId(Integer.valueOf(modelName.substring(5)));
        imagesLogEntity.setImagesLog(exec);
        imagesLogService.insert(imagesLogEntity);


        VisiAlgNode visiAlgNode=new VisiAlgNode();
        visiAlgNode.setUserId(1);
        visiAlgNode.setAlgnodeName(algorithmName);
        visiAlgNode.setAlgnodeImage(harborUrl+"/library/"+algorithmName+":latest");
        visiAlgNode.setAlgoparatempJson("{\"Input\":{\"ParameterInput\":[],\"FileInput\":[]},\"Output\":{\"ParameterOutput\": [],\"FileOutput\": []}}");
        visiAlgNode.setAlgodescription(algorithmName);
        visiAlgNode.setAlgotreetype("智能应用");
        visiAlgNodeService.insert(visiAlgNode);

        //将构建好的镜像也存入数据库
        ImagesEntity imagesEntity=new ImagesEntity();
        imagesEntity.setImageName(algorithmName);
        imagesEntity.setImageTag("latest");
        imagesEntity.setCreateTime(new Date());
        imagesEntity.setImageType("应用镜像");
        imagesEntity.setBuildEnvironment("s2i-binary");
        imagesEntity.setImageDescription("未发布");
        imagesEntity.setCreatorName(userName);
        imagesService.save(imagesEntity);

        MyWebSocket.sendMessage("制作完成");
        //镜像制作完成后将镜像构建信息改为已发布
        modelEntity.setConstructMessage("已发布");
        modelEntity.setRemark("已发布");
        modelService.updateById(modelEntity);
        modelService.updateConstructMessage(modelEntity);
        return R.ok();
    }

    /**
     * 获取传统算法参数信息
     * @param jsonData
     * @return
     */
    @PostMapping("getTraParam")
    public R getTraParam(@RequestBody String jsonData){
        JsonObject jsonObject = GsonUtil.convertJsonObject(jsonData);
        //获取算法具体名称
        String algorithmName = jsonObject.get("algorithmName").getAsString();

        Long algorithmId=minioAlgorithmService.findBelongAlgId(algorithmName);
        List<AlgorithmParameter> algorithmParameters=algorithmParameterService.selectByPrimaryKey(algorithmId);
        List<AlgorithmResult> algorithmResults=algorithmResultService.selectByPrimaryKey(algorithmId);
        return R.ok().put("params",algorithmParameters).put("results",algorithmResults);
    }

    @PostMapping("traAlgorithmPublished")
    public R traAlgorithmPublished(@RequestBody Map data) throws IOException, JSchException {
        String userName=ShiroUtils.getUserEntity().getUsername();
        String paramJson= JSON.toJSONString(data.get("params"));
        //获取算法具体名称
        String algorithmName = (String) data.get("algorithmName");
        System.out.println(paramJson);
        System.out.println(algorithmName);
        //获取model+id
        String modelName = minioAlgorithmService.findModelByName(algorithmName);
        //获取算法应用运行文件
        String appFile = minioAlgorithmService.findAppFileByName(algorithmName);
        //获取算法镜像主文件
        String imageFile=minioAlgorithmService.findImageFileByName(algorithmName);
        //下载算法文件到服务器指定路径
        ModelEntity modelEntity=new ModelEntity();
        modelEntity.setModelId(Long.parseLong(modelName.substring(5)));
        modelEntity.setConstructMessage("算法下载中");
        modelService.updateConstructMessage(modelEntity);
        algorithmService.algorithmDownloadToServer(modelName);
        MyWebSocket.sendMessage("下载完成");
        //下载完成后将镜像构建信息改为镜像制作中
        modelEntity.setConstructMessage("镜像制作中");
        modelService.updateConstructMessage(modelEntity);
        //algorithmService.algorithmDownload(modelName);
        Long algorithmId=minioAlgorithmService.findBelongAlgId(algorithmName);
        List<AlgorithmParameter> algorithmParameters=algorithmParameterService.selectByPrimaryKey(algorithmId);


        String appDockerfileShell="FROM "+harborUrl+"/library/python3_base:v1.0\n" +
                "ENV CONFIG /\n" +
                "COPY ./" + "%s" + " $CONFIG\n" +
                "CMD [\"python\", \"" + "%s" + "\"]";
        String[] appShellArgs = {modelName, appFile, modelName};
        String appDockerfilePath=tempFileLocation+"/appDockerfile";
        JavaShellUtil.generate(appDockerfileShell, appShellArgs, appDockerfilePath);

        String DockerfileShell = "FROM "+harborUrl+"/library/python3_base:v1.0\n" +
                "WORKDIR /\n" +
                "ENV CONFIG /\n";
        for(int i=0;i<algorithmParameters.size();i++){
            DockerfileShell+="ENV "+algorithmParameters.get(i).getAlgorithmParameterName().toUpperCase()+" \""+algorithmParameters.get(i).getAlgorithmParameterName()+"\"\n";
        }
        DockerfileShell+=
                "COPY ./" + "%s" + " $CONFIG\n" +
                "CMD python" + " %s";
        for(int i=0;i<algorithmParameters.size();i++){
            DockerfileShell+=" $"+algorithmParameters.get(i).getAlgorithmParameterName().toUpperCase();
        }

        String[] shellArgs = {modelName, imageFile, modelName};
        String DockerfilePath = tempFileLocation+"/Dockerfile";
        JavaShellUtil.generate(DockerfileShell, shellArgs, DockerfilePath);
        String buildShell = "#!/bin/bash\n" +
                "cd /home/mkcloud/algorithm\n" +
                "docker build -t " +harborUrl+"/library/" + algorithmName + " -f appDockerfile .\n"+
                "docker build -t " +harborUrl+"/library/" + algorithmName + "image .\n"+
                "docker push "+harborUrl+"/library/" + algorithmName+ " \n"+
                "docker push "+harborUrl+"/library/" + algorithmName+"image";
        shellArgs = new String[]{modelName, modelName, modelName, modelName};
        String buildShellPath = tempFileLocation+"/buildShell.sh";
        JavaShellUtil.generate(buildShell, shellArgs, buildShellPath);
        String command = "sh /home/mkcloud/algorithm/buildShell.sh";
        File appDockerfile=new File(tempFileLocation+"/appDockerfile");
        File Dockerfile=new File(tempFileLocation+"/Dockerfile");
        File buildShellSh=new File(tempFileLocation+"/buildShell.sh");
        FTPUtils.uploadFile(".","appDockerfile",new FileInputStream(appDockerfile));
        FTPUtils.uploadFile(".","Dockerfile",new FileInputStream(Dockerfile));
        FTPUtils.uploadFile(".","buildShell.sh",new FileInputStream(buildShellSh));

        String exec=FTPUtils.execCmd(command);
        ImagesLogEntity imagesLogEntity=new ImagesLogEntity();
        imagesLogEntity.setModelId(Integer.valueOf(modelName.substring(5)));
        imagesLogEntity.setImagesLog(exec);
        imagesLogService.insert(imagesLogEntity);

        VisiAlgNode visiAlgNode=new VisiAlgNode();
        visiAlgNode.setUserId(1);
        visiAlgNode.setAlgnodeName(algorithmName);
        visiAlgNode.setAlgnodeImage(harborUrl+"/library/"+algorithmName+"image:latest");
        visiAlgNode.setAlgoparatempJson(paramJson);
        visiAlgNode.setAlgodescription(algorithmName);
        visiAlgNode.setAlgotreetype("传统算法");
        visiAlgNodeService.insert(visiAlgNode);

        //将构建好的镜像也存入数据库
        ImagesEntity imagesEntity=new ImagesEntity();
        imagesEntity.setImageName(algorithmName);
        imagesEntity.setImageTag("latest");
        imagesEntity.setCreateTime(new Date());
        imagesEntity.setImageType("传统算法镜像");
        imagesEntity.setBuildEnvironment("s2i-binary");
        imagesEntity.setImageDescription("未发布");
        imagesEntity.setCreatorName(userName);
        imagesService.save(imagesEntity);

        MyWebSocket.sendMessage("制作完成");
        //镜像制作完成后将镜像构建信息改为已发布
        modelEntity.setConstructMessage("已发布");
        modelEntity.setRemark("已发布");
        modelService.updateById(modelEntity);
        modelService.updateConstructMessage(modelEntity);
        return R.ok();
    }



    /**
     * 算法启动，即应用制作
     *
     * @return
     */
    @PostMapping("algorithmStart")
    public String algorithmStart(@RequestBody String jsonData) {
        HashMap<String, String> args = applicationService.getArgs(jsonData);
        applicationService.applicationDryRun_V2(args);
        applicationService.deploymentDryRun_V2(args);
        applicationService.serviceDryRun_V2(args);
        applicationService.application_V2(args);
        applicationService.deployment_V2(args);
        String res = applicationService.service_V2(args);
        return res;
    }

    /**
     * 获取制作镜像的日志
     * @param jsonData
     * @return
     */
    @PostMapping("imagesLog")
    public R imageLog(@RequestBody String jsonData){
        JsonObject jsonObject = GsonUtil.convertJsonObject(jsonData);
        String modelId = jsonObject.get("modelId").getAsString();
        ImagesLogEntity imagesLogEntity=imagesLogService.selectByModelId(Integer.parseInt(modelId));
        return R.ok().put("imagesLog",imagesLogEntity.getImagesLog());
    }



}
