package com.its.dsrc.xnettcp.dsrc.process.response;

import com.beanit.asn1bean.ber.types.BerInteger;
import com.beanit.asn1bean.ber.types.BerOctetString;
import com.beanit.asn1dsrc.dsrc.C2CAuthenticatedMessage;
import com.beanit.asn1dsrc.dsrc.FrED;
import com.beanit.asn1dsrc.dsrc.PDUs;
import com.beanit.asn1dsrc.enums.eAuthInfo;
import com.beanit.asn1dsrc.util.DsrcAsn1Utils;
import com.its.app.utils.NettyUtils;
import com.its.dsrc.config.RunningConfig;
import com.its.dsrc.entity.TbRseCtlr;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;

import java.math.BigInteger;

@Slf4j
public class FredResponse implements DsrcAsn1Response {
    private TbRseCtlr obj;
    private ChannelHandlerContext ctx;
    private C2CAuthenticatedMessage c2c;

    public FredResponse(TbRseCtlr obj, ChannelHandlerContext ctx, C2CAuthenticatedMessage c2c) {
        this.obj = obj;
        this.ctx = ctx;
        this.c2c = c2c;
    }

    @Override
    public boolean response(RunningConfig runningConfig) {
        String ipAddress = NettyUtils.getRemoteIpAddress(this.ctx.channel());
        log.debug("FredResponse.response: {}", ipAddress);

        // 세션 연결 유지를 위해 Fred 메시지 전송
        PDUs pdus = this.c2c.getPdu();
        byte[] auth = { (byte) eAuthInfo.AI_FrED.getValue() };
        C2CAuthenticatedMessage resC2c = new C2CAuthenticatedMessage();
        resC2c.setDatexDataPacketNumber(new BerInteger(this.obj.getSeq().nextValue()));
        resC2c.setDatexDataPacketPriorityNumber(new BerInteger(1));
        resC2c.setDatexAuthenticationInfoText(new BerOctetString(auth));
        //resC2c.setOptions(DsrcAsn1Utils.swapHeaderOptions(this.obj.getHeaderOptions()));
        resC2c.setOptions(DsrcAsn1Utils.getDefaultOptions());
        resC2c.setPdu(pdus);

        /**
         * TODO: 클라이언트 모드로 동작시 FrED를 다시 전송하지 않는다.
         */
//        ChannelFuture f = this.ctx.channel().writeAndFlush(resC2c);
//        f.awaitUninterruptibly();
//        if (f.isDone() || f.isSuccess()) {
//            log.info("FredResponse.response: {}, Send OK", ipAddress);
//        } else {
//            log.error("FredResponse.response: {}, Send Failed", ipAddress);
//        }
        return true;
    }

    public static boolean sendFrED(TbRseCtlr obj, Channel channel) {
        String ipAddress = NettyUtils.getRemoteIpAddress(channel);
        log.debug("FredResponse.sendFrED: {}", ipAddress);

        // 세션 연결 유지를 위해 Fred 메시지 전송
        PDUs pdus = new PDUs();
        FrED fred = new FrED(new BigInteger(String.valueOf(9871)));
        pdus.setFred(fred);

        byte[] auth = { (byte) eAuthInfo.AI_FrED.getValue() };
        C2CAuthenticatedMessage resC2c = new C2CAuthenticatedMessage();
        resC2c.setDatexDataPacketNumber(new BerInteger(obj.getSeq().nextValue()));
        resC2c.setDatexDataPacketPriorityNumber(new BerInteger(1));
        resC2c.setDatexAuthenticationInfoText(new BerOctetString(auth));
        //resC2c.setOptions(DsrcAsn1Utils.swapHeaderOptions(this.obj.getHeaderOptions()));
        resC2c.setOptions(DsrcAsn1Utils.getDefaultOptions());
        resC2c.setPdu(pdus);

        ChannelFuture f = channel.writeAndFlush(resC2c);
        f.awaitUninterruptibly();
        if (f.isDone() || f.isSuccess()) {
            log.info("FredResponse.sendFrED: {}, Send OK", ipAddress);
        } else {
            log.error("FredResponse.sendFrED: {}, Send Failed", ipAddress);
        }
        return true;
    }

}
