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

import com.beanit.asn1bean.ber.types.BerEnum;
import com.beanit.asn1bean.ber.types.BerInteger;
import com.beanit.asn1bean.ber.types.BerNull;
import com.beanit.asn1bean.ber.types.BerOctetString;
import com.beanit.asn1dsrc.dsrc.*;
import com.beanit.asn1dsrc.enums.eAuthInfo;
import com.beanit.asn1dsrc.enums.ePdusPr;
import com.beanit.asn1dsrc.util.DsrcAsn1Utils;
import com.its.app.utils.NettyUtils;
import com.its.dsrc.entity.TbRseCtlr;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class DsrcAsn1Accept {

    static C2CAuthenticatedMessage makeC2CAuthenticatedMessage(TbRseCtlr obj, Channel channel, C2CAuthenticatedMessage c2c) {
        if (obj == null || channel == null || c2c == null) {
            log.info("{}. {} {}, {}", "makeC2CAuthenticatedMessage", obj, channel, c2c);
            return null;
        }

        String ipAddress = NettyUtils.getRemoteIpAddress(channel);
        C2CAuthenticatedMessage resC2c = null;
        PDUs pdus = c2c.getPdu();
        ePdusPr pdu = DsrcAsn1Utils.getPduChoice(pdus);

        byte[] accept = { (byte) eAuthInfo.AI_Accept.getValue() };
        PDUs resPdus = new PDUs();
        Accept acpt = new Accept();
        Accept.DatexAcceptType acptType = new Accept.DatexAcceptType();

        log.debug("DsrcAsn1Accept.makeC2CAuthenticatedMessage: {}, {}", ipAddress, pdu.toString());

        switch(pdu) {
        case PDUs_PR_login:
            resC2c = new C2CAuthenticatedMessage();
            Login login = pdus.getLogin();
            acptType.setLogIn(login.getDatexLoginEncodingRulesId().getBerObjectIdentifier().get(0));
            break;
        case PDUs_PR_subscripiton:
            resC2c = new C2CAuthenticatedMessage();
            Subscription subscription = c2c.getPdu().getSubscription();
            SubscriptionType subscriptionType = subscription.getDatexSubscribeType();
            BerEnum cancelReasonCd = subscriptionType.getDatexSubscribeCancelReasonCd();
            if (subscriptionType != null) {
                // Subscription
                SubscriptionData subscriptionData = subscriptionType.getSubscription();
                SubscriptionMode subscriptionMode = subscriptionData.getDatexSubscribeMode();
                BerNull single = subscriptionMode.getSingle();
                Registered eventDriven = subscriptionMode.getEventDriven();
                Registered periodic = subscriptionMode.getPeriodic();

                if (single != null) {
                    acptType.setSingleSubscription(new BerNull());
                }
                else if (eventDriven != null) {
                    Registered.Continuous cont = eventDriven.getContinuous();
                    if (cont != null) {
                        acptType.setRegisteredSubscription(cont.getDatexRegisteredUpdateDelayQty());
                    }
                    else {
                        acptType.setRegisteredSubscription(subscription.getDatexSubscribeSerialNbr());
                    }
                }
                else if (periodic != null) {
                    Registered.Continuous cont = periodic.getContinuous();
                    if (cont != null) {
                        acptType.setRegisteredSubscription(cont.getDatexRegisteredUpdateDelayQty());
                    }
                    else {
                        acptType.setRegisteredSubscription(subscription.getDatexSubscribeSerialNbr());
                    }
                }
                else {
                    return null;
                }
            }
            else if (cancelReasonCd != null) {
                // Cancel
                acptType.setRegisteredSubscription(subscription.getDatexSubscribeSerialNbr());
            }
            break;
        case PDUs_PR_publication:
            resC2c = new C2CAuthenticatedMessage();
            BerNull berNull = new BerNull();
            acptType.setPublication(berNull);
            break;
        default:
            break;
        }

        if (resC2c != null) {
            acpt.setDatexAcceptPacketNbr(c2c.getDatexDataPacketNumber());
            acpt.setDatexAcceptType(acptType);
            resPdus.setAccept(acpt);

            resC2c.setDatexAuthenticationInfoText(new BerOctetString(accept));
            resC2c.setDatexDataPacketNumber(new BerInteger(obj.getSeq().nextValue()));
            resC2c.setDatexDataPacketPriorityNumber(new BerInteger(0));
            //resC2c.setOptions(DsrcAsn1Utils.swapHeaderOptions(c2c.getOptions()));
            resC2c.setOptions(DsrcAsn1Utils.swapHeaderOptions(obj.getHeaderOptions()));
            resC2c.setPdu(resPdus);
        }
        return resC2c;
    }
}
