package com.yihu.hos.monitor.service;

import com.mongodb.*;
import com.yihu.hos.common.constants.ContextAttributes;
import com.yihu.hos.core.datatype.CollectionUtil;
import com.yihu.hos.monitor.dao.ServiceMonitorDao;
import com.yihu.hos.system.model.SystemServiceEndpoint;
import com.yihu.hos.system.model.SystemServiceFlow;
import com.yihu.hos.system.model.SystemServiceFlowConfig;
import com.yihu.hos.system.service.FlowManager;
import com.yihu.hos.tenant.model.TenantSession;
import com.yihu.hos.web.framework.constant.ServiceFlowConstant;
import com.yihu.hos.web.framework.model.Result;
import com.yihu.hos.web.framework.model.TreeView;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by chenweida on 2016/1/27.
 */
@Service("ServiceMonitorService")
public class ServiceMonitorService {
    public static final String BEAN_ID = "ServiceMonitorService";
    public static final String dbName = "log";
    public static final String tableName = "serviceMetrics";
    public static final String serviceFlow = "serviceFlow";
    public static final String configuration = "configuration";

    @Autowired
    private MongoOperations mongoOperations;

    @Autowired
    private Mongo mongo;

    @Autowired
    private ServiceMonitorDao serviceMonitorDao;

    @Resource(name = FlowManager.BEAN_ID)
    private FlowManager flowManager;

    public Result metrics(HttpSession session,String id, String beginTime, String endTime) throws Exception {
        String name;
        String code;
        String description;
        TenantSession tenantSession = (TenantSession)session.getAttribute(ContextAttributes.TENANT_SESSION);
        if (id.contains("flow")) {
            Integer flowId = Integer.parseInt(id.replace("flow", ""));
            SystemServiceFlow systemServiceFlow = serviceMonitorDao.getFlowById(flowId);
            name = systemServiceFlow.getName();
            code = systemServiceFlow.getCode();
            description = systemServiceFlow.getDescription();
        } else {
            String endpointId =id.replace("endpoint", "");
            SystemServiceEndpoint systemServiceEndpoint = serviceMonitorDao.getEndpointById(endpointId);
            name = systemServiceEndpoint.getName();
            code = systemServiceEndpoint.getCode();
            description = systemServiceEndpoint.getDescription();
        }
        JSONObject serviceInfo = new JSONObject();
        serviceInfo.put("name", name);
        serviceInfo.put("description", description);

        mongoOperations = new MongoTemplate(mongo, dbName);
        DBCollection metrics = mongoOperations.getCollection(tableName);
        BasicDBObject queryObject = new BasicDBObject().append(QueryOperators.AND,
                new BasicDBObject[]{
                        new BasicDBObject().append("createTime",
                                new BasicDBObject().append(QueryOperators.GTE, beginTime)),
                        new BasicDBObject().append("createTime",
                                new BasicDBObject().append(QueryOperators.LT, endTime)),
                        new BasicDBObject("name", code),
                        new BasicDBObject("tenant", tenantSession.getTenant())});

        JSONObject result = new JSONObject();
        DBCursor cursor = metrics.find(queryObject);
        JSONArray bandwidth = new JSONArray();
        JSONArray qps = new JSONArray();
        JSONArray usage = new JSONArray();
        JSONArray delay = new JSONArray();
        while(cursor.hasNext()) {
            DBObject dbObject = cursor.next();
            dbObject.removeField("_id");
            String type = dbObject.get("type").toString();
            switch (type) {
                case "bandwidth" : bandwidth.put(dbObject);break;
                case "qps" : qps.put(dbObject);break;
                case "usage" : usage.put(dbObject);break;
                case "delay" : delay.put(dbObject);break;

            }
        }
        result.put("bandwidth", bandwidth);
        result.put("qps", qps);
        result.put("usage", usage);
        result.put("delay", delay);
        result.put("serviceInfo", serviceInfo);
        return Result.success(result.toString());
    }

    public Result getServiceTreeList() throws Exception {
        List<TreeView> treeList = new ArrayList<>();

        List<SystemServiceFlow> flowList = serviceMonitorDao.getFlowsByType(ServiceFlowConstant.CLASS);
        List<SystemServiceFlowConfig> flowEndpointList = serviceMonitorDao.getAllFlowEndpoints();
        List<SystemServiceEndpoint> endpointList = serviceMonitorDao.getAllEndpoints();
        Map<Integer, List<String>> flowEndpointMap = new HashMap<>();
        Map<String, SystemServiceEndpoint> endpointMap = new HashMap<>();

        for (SystemServiceFlowConfig systemServiceFlowConfig : flowEndpointList) {
            List<String> endpointIdList;
            if (flowEndpointMap.containsKey(systemServiceFlowConfig.getFlowId())) {
                endpointIdList = flowEndpointMap.get(systemServiceFlowConfig.getFlowId());
            } else {
                endpointIdList = new ArrayList<>();
            }
            endpointIdList.add(systemServiceFlowConfig.getEndpointId());
            flowEndpointMap.put(systemServiceFlowConfig.getFlowId(), endpointIdList);
        }

        for (SystemServiceEndpoint endpoint : endpointList) {
            endpointMap.put(endpoint.getId(), endpoint);
        }

        for (SystemServiceFlow flow : flowList) {
                TreeView rootTree = new TreeView();
                rootTree.setIschecked(false);
                rootTree.setId("flow" + flow.getId());
                rootTree.setPid("-1");
                rootTree.setText(flow.getName());
                treeList.add(rootTree);
                List<String> endpointIdList = flowEndpointMap.get(flow.getId());
                if (!CollectionUtil.isEmpty(endpointIdList)) {
                    for (String endpointId : endpointIdList) {
                        SystemServiceEndpoint endpoint = endpointMap.get(endpointId);
                        TreeView childTree = new TreeView();
                        childTree.setIschecked(false);
                        childTree.setId("endpoint" + endpoint.getId());
                        childTree.setPid("flow" + flow.getId());
                        childTree.setText(endpoint.getName());
                        treeList.add(childTree);
                    }
            }
        }
        JSONArray jsonArray = new JSONArray(treeList);

        return Result.success(jsonArray.toString());
    }

    public boolean serviceStatus(String routeCode){
        boolean succ = false;
//        MongoDatabase db = mongoConfig.mongoClient().getDatabase(configuration);
//        MongoCollection<Document> collection = db.getCollection(serviceFlow);

        return succ;
    }

}
