package com.activiti6.controller;

import com.activiti6.common.utils.MultipartFileToFile;
import com.activiti6.entity.AjaxEntityVo;
import com.activiti6.entity.MyFormData;
import com.activiti6.entity.MyFormDataZip;
import com.activiti6.mapper.MyFormDataMapper;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.Process;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Model;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

@Controller
@RequestMapping("zip")
public class ZipFileController extends BaseController {


    protected final Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private MyFormDataMapper myFormDataMapper;

    /*文件上传*/
    @PostMapping("upload")
    public AjaxEntityVo upload(MultipartFile file) throws Exception {

        File parseFile = MultipartFileToFile.multipartFileToFile(file);
        ZipFile zip = null;
        try {
            //指定编码，否则压缩包里面不能有中文目录
            zip = new ZipFile(parseFile, StandardCharsets.UTF_8);
            String msg = null;
            List<MyFormData> list = new ArrayList();
            for (Enumeration entries = zip.entries(); entries.hasMoreElements(); ) {
                ZipEntry entry = (ZipEntry) entries.nextElement();
                String zipEntryName = entry.getName();
                String filterName = zipEntryName.split("\\.")[1].toLowerCase();
                if (filterName.contains("o") || filterName.contains("m") || filterName.contains("n")) {
                    //fileName +=zipEntryName+",";
                    InputStream in = zip.getInputStream(entry);
                    if ("bpmn".equals(filterName)) {
                        //pushBpmn(zipEntryName, in);
                        msg = convertInputStreamToModel(in);
                    }
                    if ("json".equals(filterName)) {
                        list.add(addMyFormData(zipEntryName, in));
                    }
                }
            }
            if (!StringUtils.isEmpty(msg)) {
                myFormDataMapper.insertList(list);
            }
            //必须关闭，否则无法删除该zip文件
            zip.close();
        } catch (Exception e) {
            log.info("文件解析出错：文件名------->" + parseFile.getName());
            e.printStackTrace();
            throw new Exception(e.getMessage());

        }
        return success();
    }

    private MyFormData addMyFormData(String zipEntryName, InputStream in) {
        log.info("文件名------->" + zipEntryName);
        String defaultString = null;
        try {
            StringBuffer message = new StringBuffer();
            BufferedReader br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
            String line = null;
            while ((line = br.readLine()) != null) {
                message.append(line);
            }
            defaultString = message.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        String result = defaultString.replace("\r\n", "").replaceAll(" +", "");
        MyFormDataZip jsonData = JSONObject.parseObject(result, MyFormDataZip.class);
        MyFormData myFormData = new MyFormData();
        BeanUtils.copyProperties(jsonData, myFormData);
        Object jsonData1 = jsonData.getJsonData();
        String string = JSON.toJSONString(jsonData1);
        myFormData.setJsonData(string);
        return myFormData;
    }

    private void pushBpmn(String zipEntryName, InputStream in) {
        try {
            repositoryService.createDeployment()
                    .addInputStream(zipEntryName, in).deploy();
        } catch (Exception e) {
            log.info("文件解析出错：文件名------->");
        }
    }

    public String convertInputStreamToModel(InputStream is) throws Exception {
        String modelId = null;
        XMLInputFactory xif = XMLInputFactory.newInstance();
        InputStreamReader isr = null;
        XMLStreamReader xtr = null;
        try {
            isr = new InputStreamReader(is, "utf-8");
            xtr = xif.createXMLStreamReader(isr);
            BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr);
            // 处理异常
            if (bpmnModel.getMainProcess() == null
                    || bpmnModel.getMainProcess().getId() == null) {
                throw new Exception("模板文件可能存在问题，请检查后重试！");
            }

            ObjectNode modelNode = new BpmnJsonConverter().convertToJson(bpmnModel);
            Model modelData = repositoryService.newModel();
            org.activiti.bpmn.model.Process process = bpmnModel.getMainProcess();
            checkName(process);
            String key = process.getId();
            String name = process.getName();
            String description = process.getDocumentation();
            modelData.setKey(key);
            modelData.setName(name);

            ObjectNode modelObjectNode = new ObjectMapper().createObjectNode();
            modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, name);
            modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
            modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
            modelData.setMetaInfo(modelObjectNode.toString());
            repositoryService.saveModel(modelData);
            repositoryService.addModelEditorSource(modelData.getId(), modelNode.toString().getBytes("utf-8"));
            modelId = modelData.getId();
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(e.getMessage());
        } finally {
            try {
                xtr.close();
            } catch (XMLStreamException e) {
                e.printStackTrace();
            }
            try {
                isr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return modelId;
    }

    private void checkName(Process process) throws Exception {
        String key = process.getId();
        List<Model> list = repositoryService.createModelQuery().modelKey(key).list();
        if (list.size() > 0) {
            throw new Exception("该流程文件已存在无法上传");
        }
    }
}
