package com.unis.flowable.server.service;

import java.util.ArrayList;
import java.util.List;

import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.editor.language.json.converter.util.CollectionUtils;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.flowable.ui.common.security.SecurityUtils;
import org.flowable.ui.common.service.exception.InternalServerErrorException;
import org.flowable.ui.modeler.domain.AbstractModel;
import org.flowable.ui.modeler.domain.AppDefinition;
import org.flowable.ui.modeler.model.AppDefinitionListModelRepresentation;
import org.flowable.ui.modeler.model.ModelKeyRepresentation;
import org.flowable.ui.modeler.model.ModelRepresentation;
import org.flowable.ui.modeler.repository.ModelRepository;
import org.flowable.ui.modeler.serviceapi.ModelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.unis.flowable.server.config.PageResponse;

@Service
public class FlowModelService {
	
	@Autowired
	private RepositoryService repositoryService;
	protected ObjectMapper objectMapper = new ObjectMapper();
	
	@Autowired
	private ModelService modelService;
	
	@Autowired
	private ModelRepository modelRepository;

	public List<ModelRepresentation> modelList(String orgId, Integer pageNum, Integer pageSize) {
		new PageResponse().enablePage(pageNum,pageSize);
		
		//ModelQuery modelQuery = repositoryService.createModelQuery().latestVersion().orderByCreateTime().desc().listPage(pageNum,pageSize);
		//List<Model> model= repositoryService.createModelQuery().latestVersion().listPage(pageNum,pageSize);
		
		List<ModelRepresentation> resultList = new ArrayList<>();
        List<org.flowable.ui.modeler.domain.Model> models = null;

            models = modelRepository.findByModelType(0, null);
        if (CollectionUtils.isNotEmpty(models)) {
            List<String> addedModelIds = new ArrayList<>();
            for (org.flowable.ui.modeler.domain.Model model : models) {
                if (!addedModelIds.contains(model.getId())) {
                    addedModelIds.add(model.getId());
                    ModelRepresentation representation = createModelRepresentation(model);
                    resultList.add(representation);
                }
            }
        }
		
		
		return resultList;
	}
	
	protected ModelRepresentation createModelRepresentation(AbstractModel model) {
        ModelRepresentation representation = null;
        if (model.getModelType() != null && model.getModelType() == 3) {
            representation = new AppDefinitionListModelRepresentation(model);

            AppDefinition appDefinition = null;
            try {
                appDefinition = objectMapper.readValue(model.getModelEditorJson(), AppDefinition.class);
            } catch (Exception e) {
                throw new InternalServerErrorException("Could not deserialize app definition");
            }
            ((AppDefinitionListModelRepresentation) representation).setAppDefinition(appDefinition);

        } else {
            representation = new ModelRepresentation(model);
        }
        return representation;
    }

	@SuppressWarnings("unused")
	public int deploy(String modelId) {
		org.flowable.ui.modeler.domain.Model modelData =modelService.getModel(modelId);
		byte[] bytes = modelService.getBpmnXML(modelData);
		if(bytes==null){
		    return 0;
		}

		BpmnModel model = modelService.getBpmnModel(modelData);
		if(bytes==null){
		    return 0;
		}
		byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);
		String processName = modelData.getName()+".bpmn20.xml";
		Deployment deployment = repositoryService.createDeployment()
		        .name(modelData.getName())
		        .addBytes(processName,bpmnBytes)
		        .deploy();
	    return 1;
	}
	
	public org.flowable.ui.modeler.domain.Model create(ModelRepresentation modelRepresentation) {
		 ModelKeyRepresentation modelKeyInfo = modelService.validateModelKey(null, modelRepresentation.getModelType(), modelRepresentation.getKey());
		 if(modelKeyInfo.isKeyAlreadyExists()) {
			 return null;
		 }
		 String json = modelService.createModelJson(modelRepresentation);

		 org.flowable.ui.modeler.domain.Model newModel = modelService.createModel(modelRepresentation, json, SecurityUtils.getCurrentUserObject());
		return newModel;
	}

	public int delete(String id) {
		modelService.deleteModel(id);
		return 1;
	}

}
