package com.xhpc.pp.logic;

import com.xhpc.common.enums.StationDeviceEnum;
import com.xhpc.evcs.dto.ConnectorStatusInfo;
import com.xhpc.pp.domain.XhpcDeviceMessage;
import com.xhpc.pp.mapper.XhpcDeviceMessageMapper;
import com.xhpc.pp.tx.ServiceParameter;
import com.xhpc.pp.tx.ServiceResult;
import com.xhpc.pp.tx.logic.ServiceLogic;
import com.xhpc.pp.utils.security.CRCCalculator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

import static com.xhpc.common.data.redis.StaticBeanUtil.REDIS;
import static com.xhpc.common.data.redis.StaticBeanUtil.seqHex;
import static com.xhpc.pp.config.EarlierBeanConf.getLocalIPAndPort;
import static com.xhpc.pp.utils.HexUtils.toBytes;

@Lazy
@Component("RegisterLogic")
public class RegisterLogic implements ServiceLogic {

    public static final String DISCONNECTED = "离线";
    public static final String REGISTERED = "已注册";
    private static final Logger log = LoggerFactory.getLogger(RegisterLogic.class);

    @Resource
    XhpcDeviceMessageMapper deviceMessageMapper;

    @Override
    public ServiceResult service(ServiceParameter sp) throws Exception {

        Map<String, Object> req = sp.getParameters();
        String resultCode = ServiceResult.OK;
        String hexCode = ServiceResult.HEX_00;
        String pileNo = (String) req.get("pileNo");
        Set<String> whitelist = REDIS.getCacheSet("PILE_WHITELIST");
        if (!whitelist.contains(pileNo)) {
            log.debug("pile not in whitelist ({}) ", pileNo);
            hexCode = ServiceResult.HEX_01;
            resultCode = ServiceResult.FAIL;
//        } else if (!EarlierBeanConf.ifcanreg(pileNo)) { // not a stable reliable method
//            log.debug("pile already registered ({}) ", pileNo);
//            hexCode = ServiceResult.HEX_01;
//            resultCode = ServiceResult.FAIL;
        } else {
            String pkey = "pile:".concat(pileNo);
            Map<String, Object> cachePile = REDIS.getCacheMap(pkey);
            cachePile.put("status", REGISTERED);
            String localIPAndPort = getLocalIPAndPort();
            cachePile.put("svcSrv", localIPAndPort);
            int gunNum = Integer.parseInt(req.get("gunNum").toString());
            cachePile.put("gunNum", gunNum);
            cachePile.put("firmwareVersion", new String(toBytes(req.get("hex").toString().substring(32, 48))));
            cachePile.put("version", req.get("version").toString());
            REDIS.setCacheMap("pile:".concat(pileNo), cachePile);
            for (int gunN = 1; gunN <= gunNum; gunN++) {
                String gunId = String.format("%02d", gunN);
                String gunkey = "gun:".concat(pileNo.concat(gunId));
                Map<String, Object> cacheGun = REDIS.getCacheMap(gunkey);
                cacheGun.put("status", DISCONNECTED);
                cacheGun.put("statusInt", ConnectorStatusInfo.OFF_LINE);
                cacheGun.put("svcSrv", localIPAndPort);
                cacheGun.put("version", cachePile.get("version"));
                REDIS.setCacheMap(gunkey, cacheGun);
                String svcSrvKeyNew = "svcSrvGuns:".concat(getLocalIPAndPort());
                cachePileGunSvcSrv(gunkey, svcSrvKeyNew);
                final Collection<String> cacheSvcSrvKeys = REDIS.keys("svcSrvGuns:*");
                for (String svcSrvKey : cacheSvcSrvKeys) {
                    if (!svcSrvKey.equals(svcSrvKeyNew)) {
                        REDIS.deleteSetVal(svcSrvKey, gunkey);
                    }
                }
            }
            log.debug("pile (re)registered ({}) ", pileNo);
        }
        String skey = "pile:".concat(pileNo).concat(".seqhex");
        //String seq = seqHex(skey);
        //String resultStr = "680C".concat(seq).concat("0002").concat(pileNo).concat(hexCode);

        String seq =(String) req.get("hex");
        String resultStr = "680C".concat(seq.substring(4,8)).concat("0002").concat(pileNo).concat(hexCode);
        resultStr = resultStr.concat(CRCCalculator.calcCrc(resultStr));

        // 写入设备日志表数据
        XhpcDeviceMessage deviceMessage = new XhpcDeviceMessage();
        deviceMessage.setType(StationDeviceEnum.PILE.getCode());
        deviceMessage.setSerialNumber(pileNo);
        deviceMessage.setRemark("充电桩登录认证");
        deviceMessage.setStatus(0);
        deviceMessage.setContent((String) req.get("hex"));
        deviceMessageMapper.insertByDomain(deviceMessage);

        return new ServiceResult(toBytes(resultStr), resultCode);
    }

    private void cachePileGunSvcSrv(String gunkey, String svcSrvKey) {

        Set<String> svcPileGuns = REDIS.getCacheSet(svcSrvKey);
        svcPileGuns.add(gunkey);
        REDIS.setCacheSet(svcSrvKey, svcPileGuns);
    }


    public static void main(String[] args) {
        String version = new String(toBytes("56302E302E310000"));

        System.out.println("version: " + version);
    }
}
