package cn.ibizlab.codegen.model;

import cn.ibizlab.codegen.utils.StringAdvUtils;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import net.ibizsys.model.IPSSystem;
import net.ibizsys.model.codelist.IPSCodeList;
import net.ibizsys.model.pub.IPSSysSFPub;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;

@Getter
@Setter
@NoArgsConstructor
@Accessors(chain = true)
public class SystemModel extends BaseModel {

    public SystemModel(IPSSystem system) {
        this.opt = system;
        system.getAllPSSystemModules().forEach(item -> {

        });
        if (!ObjectUtils.isEmpty(system.getDefaultPSSysSFPub())) {


            if (this.pub == null)
                this.pub = system.getDefaultPSSysSFPub();
        }
        if (this.pub != null) {
            this.setCodeName(this.pub.getCodeName());
            this.setName(system.getName());
            this.setProjectName(this.pub.getCodeName().toLowerCase());
            this.setProjectDesc(StringAdvUtils.pascalcase(this.pub.getCodeName().toLowerCase()));
            this.setMemo(StringUtils.isEmpty(pub.getMemo())?pub.getName():pub.getMemo());
            this.setPackageName(this.pub.getPKGCodeName());
            this.setModelFolder((StringUtils.isEmpty(this.pub.getModelFolder())?"model":this.pub.getModelFolder()));
        } else {
            this.setCodeName(system.getCodeName());
            this.setName(system.getName());
            this.setProjectName(system.getCodeName().toLowerCase());
            this.setProjectDesc(system.getName());
            this.setMemo(StringUtils.isEmpty(system.getLogicName())?system.getName():system.getLogicName());
            this.setPackageName(system.getCodeName().toLowerCase());
            this.setModelFolder("model");
        }
        if(StringUtils.isEmpty(system.getDeploySysId())||system.getDeploySysId().length()>16)
            this.setDeploySysId(this.getName());
        else
            this.setDeploySysId(system.getDeploySysId());
        getEntitiesMap();
        getClientMap();
    }

    public IPSSystem getSystem() {
        return (IPSSystem) opt;
    }

    private String projectName;

    private String projectDesc;

    private String packageName;

    private String modelFolderPath;

    private String memo;

    private String deploySysId;

    private String modelFolder;

    private boolean enableDS = false;
    private boolean enableES = false;
    private boolean enableMongo = false;
    private boolean enableMQ = false;
    private boolean enableOAuth2 = false;
    private boolean enableGlobalTransaction = false;
    private boolean enableMysql = false;
    private boolean enableOracle = false;
    private boolean enableDameng = false;
    private boolean enablePostgreSQL = false;
    private boolean enableDyna = false;
    private boolean enableWorkflow = false;

    private IPSSysSFPub pub;

    private Set<String> mqSubscribes;


    private Map<String, EntityModel> entitiesMap;

    public synchronized Map<String, EntityModel> getEntitiesMap() {
        if (entitiesMap == null) {
            entitiesMap = new LinkedHashMap<>();
            getSystem().getAllPSDataEntities().forEach(entity -> {
                if ((entity.getStorageMode() == 1 || entity.getStorageMode() == 2) && "DEFAULT".equals(entity.getDSLink()))
                    enableDS = true;
                if (entity.getStorageMode() == 2)
                    enableMongo = true;
                if (ObjectUtils.isEmpty(entity.getAllPSDEWFs()))
                    enableWorkflow = true;
                if (!enableES && "elasticsearch".equalsIgnoreCase(entity.getUserTag()))
                    enableES = true;
                if (!enableMQ && !ObjectUtils.isEmpty(entity.getAllPSDEDataSyncs()))
                    enableMQ = true;
                if (entity.getAllPSDEDataSyncs() != null) {
                    entity.getAllPSDEDataSyncs().forEach(sync -> {
                        if (sync.getInPSSysDataSyncAgent() != null) {
                            if (mqSubscribes == null) mqSubscribes = new LinkedHashSet<>();
                            mqSubscribes.add(sync.getCodeName());
                        }
                    });
                }
                entitiesMap.put(entity.getCodeName(), new EntityModel(this, entity));
            });
        }
        return entitiesMap;
    }

    private Map<String, WorkflowModel> workflowsMap;

    public synchronized Map<String, WorkflowModel> getWorkflowsMap() {
        if (workflowsMap == null) {
            try {
                workflowsMap = new LinkedHashMap<>();
                getSystem().getAllPSWorkflows().forEach(workflow -> {
                    workflow.getPSWFVersions().forEach(workflowVersion -> {
                        workflowsMap.put(workflowVersion.getCodeName(), new WorkflowModel(this, workflow,workflowVersion));
                    });
                });
            } catch (Exception e) {

            }
        }
        return workflowsMap;
    }

    public Collection<WorkflowModel> getWorkflows() {
        return getWorkflowsMap().values();
    }

    private Map<String, SysUtilModel> sysUtilModelMap;

    public synchronized Map<String, SysUtilModel> getSysUtilModelMaps() {
        if (sysUtilModelMap == null) {
            try {
                sysUtilModelMap = new LinkedHashMap<>();
                getSystem().getAllPSSysUtils().forEach(iPSSysUtil -> {
                    sysUtilModelMap.put(iPSSysUtil.getCodeName(), new SysUtilModel(iPSSysUtil));
                });
            } catch (Exception e) {

            }
        }
        return sysUtilModelMap;
    }

    public Collection<SysUtilModel> getSysUtils() {
        return getSysUtilModelMaps().values();
    }

    public boolean isHasMsgTemplate() {
        return !ObjectUtils.isEmpty(getSystem().getAllPSSysMsgTempls());
    }

    public boolean isHasRuntimeDict() {
        if (getSystem().getAllPSCodeLists() != null) {
            for (IPSCodeList dict : getSystem().getAllPSCodeLists()) {
                if ("RUNTIME".equalsIgnoreCase(dict.getPredefinedType()))
                    return true;
            }
        }
        return false;
    }

    public Collection<EntityModel> getEntities() {
        return getEntitiesMap().values();
    }

    private Map<String, AppModel> appsMap;

    private AppModel defaultApp;

    private ApiModel defaultApi;

    public synchronized Map<String, AppModel> getAppsMap() {
        if (appsMap == null) {
            appsMap = new LinkedHashMap<>();
            if (getSystem().getAllPSApps() != null) {
                getSystem().getAllPSApps().forEach(item -> {
                    AppModel appModel=new AppModel(item).setSystem(this);
                    if(item.getDefaultFlag())
                        defaultApp=appModel;
                    appsMap.put(item.getCodeName(),appModel);
                });
                if(defaultApp==null)
                    defaultApp=appsMap.values().iterator().next();
            }
        }
        return appsMap;
    }

    public Collection<AppModel> getApps() {
        return getAppsMap().values();
    }

    private Map<String, ApiModel> apisMap;

    public synchronized Map<String, ApiModel> getApisMap() {
        if (apisMap == null) {
            try {
                apisMap = new LinkedHashMap<>();
                getSystem().getAllPSSysServiceAPIs().forEach(api -> {
                    ApiModel apiModel=new ApiModel(api).setSystem(this);
                    defaultApi=apiModel;
                    apisMap.put(api.getCodeName(), apiModel);
                });
                if(defaultApi==null)
                    defaultApi=apisMap.values().iterator().next();
            } catch (Exception e) {

            }
        }
        return apisMap;
    }

    private String apiProfileId;
    public String getApiProfileId()
    {
        if(apiProfileId==null)
        {
            if(!ObjectUtils.isEmpty(getApisMap())){
                apiProfileId=getDefaultApi().getCodeName();
            }
        }
        return apiProfileId;
    }

    public Collection<ApiModel> getApis() {
        return getApisMap().values();
    }

    private Map<String, ClientModel> clientMap;

    private Map<String, List<ClientModel>> moduleClients;

    public synchronized Map<String, ClientModel> getClientMap() {
        if (clientMap == null) {
            clientMap = new LinkedHashMap<>();
            if(getSystem().getAllPSSubSysServiceAPIs()!=null)
            {
                getSystem().getAllPSSubSysServiceAPIs().forEach(subSysServiceAPI -> {
                    ClientModel subapi=new ClientModel(subSysServiceAPI).setSystem(this);
                    clientMap.put(subSysServiceAPI.getCodeName(), subapi);

                    String module=subapi.getModule();
                    if(!StringUtils.isEmpty(module))
                    {
                        if(moduleClients ==null)
                            moduleClients =new LinkedHashMap<>();
                        if(!moduleClients.containsKey(module))
                            moduleClients.put(module,new ArrayList<>());
                        moduleClients.get(module).add(subapi);
                    }

                });
            }

        }
        return clientMap;
    }

    public Collection<ClientModel> getClient() {
        return getClientMap().values();
    }


    public EntityModel getEntity(String codeName) {
        return getEntitiesMap().get(codeName);
    }


}
