package com.huatek.busi.ws.util;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import com.alibaba.dubbo.config.annotation.Reference;
import com.huatek.busi.common.CacMonitorTypeCode;
import com.huatek.busi.common.util.DecimalUtil;
import com.huatek.busi.service.cac.CacEtlFactoryService;
import com.huatek.busi.ws.protocol.CacAttr;
import com.huatek.busi.ws.protocol.CacDataNode;
import com.huatek.busi.ws.protocol.CacRequest;
import com.huatek.torch.sql.beans.Pojo;
import com.huatek.torch.util.uuid.Uuid;

/**
 * CAC监测数据报文解析
 *
 * @author anker cheng
 *
 * @Date 2019年6月26日
 */
@Component
public class CacParseFactory {
    private static final Logger logger = LoggerFactory.getLogger(CacParseFactory.class);

    @Reference(check = false)
    private CacEtlFactoryService<Pojo> cacEtlFactoryService;

    public String parse(CacRequest request, CacDataNode cacDataNode) {
        CacMonitorTypeCode cacMonitorTypeCode = CacMonitorTypeCode.from(cacDataNode.getType());
        if(cacMonitorTypeCode.getTableClass() == null) {
            logger.warn("unkonown table class: {}", cacDataNode.getType());
            return CacUtil.buildResult();
        }
        try {
            Pojo cacEntity = (Pojo)cacMonitorTypeCode.getTableClass().newInstance();
            this.parse(cacEntity, request, cacDataNode);
            cacEtlFactoryService.doDispatch(cacEntity);
        } catch (InstantiationException | IllegalAccessException e) {
            logger.error(e.getMessage(), e);
        }
        return CacUtil.buildResult();
    }

    private void parse(Pojo cacEntity, CacRequest request, CacDataNode cacDataNode) {
        //拿到cacEntity对象的所有属性
        Map<String, Field> decFieldMap = Arrays.stream(cacEntity.getClass().getDeclaredFields())
                .collect(Collectors.toMap(Field::getName, field -> field));
        //设置公共字段的值
        setFieldValue(cacEntity, decFieldMap.get("id"), Uuid.getUUID());
        setFieldValue(cacEntity, decFieldMap.get("cacId"), request.getCacMonitorData().getCacid());
        setFieldValue(cacEntity, decFieldMap.get("dataNodeNum"), DecimalUtil.getVal(request.getCacMonitorData().getDataNodeNum()));
        setFieldValue(cacEntity, decFieldMap.get("sensorId"), cacDataNode.getSensorId());
        setFieldValue(cacEntity, decFieldMap.get("cacMonitorTypeCode"), cacDataNode.getType());
        setFieldValue(cacEntity, decFieldMap.get("equipmentId"), cacDataNode.getEquipmentId());
        setFieldValue(cacEntity, decFieldMap.get("timeStamp"), cacDataNode.getTimeStamp());
        // 监测参数集合解析
        if (CollectionUtils.isEmpty(cacDataNode.getAttrs())) {
            logger.warn("datanode.attrs is empty!");
            return;
        }
        for (CacAttr cacAttr : cacDataNode.getAttrs()) {
            setFieldValue(cacEntity, getField(decFieldMap, cacAttr.getName()), cacAttr.getValue());
        }
    }

    private static Field getField(Map<String, Field> decFieldMap, String fieldName){
        for(String key : decFieldMap.keySet()) {
            if(key.equalsIgnoreCase(fieldName)) {
                return decFieldMap.get(key);
            }
        }
        return null;
    }

    /**
     * 通过属性名设置属性值,不存在的属性名忽略设置值
     * 
     * @param object
     * @param field
     * @param value
     */
    private static void setFieldValue(Object object, Field field, Object value) {
        if (field == null) {
            return;
        }
        try {
            // 取消语言访问检查
            field.setAccessible(true);
            // 给变量赋值
            field.set(object, value);
        } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
            logger.error(e.getMessage(), e);
        }
    }
}
