package com.its.dsrc.xnettcp.dsrc.process.service.impl;

import com.beanit.asn1dsrc.dsrc.*;
import com.beanit.asn1dsrc.enums.eControlDevice;
import com.beanit.asn1dsrc.enums.eObjectId;
import com.its.app.utils.NettyUtils;
import com.its.dsrc.entity.TbRseCtlr;
import com.its.dsrc.xnettcp.dsrc.process.service.ControlDeviceService;
import com.its.dsrc.xnettcp.dsrc.process.service.SubscriptionService;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.util.List;

@Slf4j
public class SubscriptionRegisterService implements SubscriptionService {
    private static SubscriptionRegisterService _instance = null;

    public static SubscriptionRegisterService getInstance() {
        if (_instance == null) {
            synchronized (SubscriptionRegisterService.class) {
                if (_instance == null)
                    _instance = new SubscriptionRegisterService();
            }
        }
        return _instance;
    }

    public SubscriptionRegisterService() {
    }

    @Override
    public boolean response(TbRseCtlr obj, Channel channel, int objectId, Subscription subscription) {
        /*
         *  SubscriptionResponse 에서 호출
         */
        String ipAddress = NettyUtils.getRemoteIpAddress(channel);
        //log.info("SubscriptionRegisterService.response: {}. ObjectId: {}", ipAddress, objectId);

        if (objectId == eObjectId.OBJ_MultiMediaData.getValue()) {
            return multiMediaDataResponse(obj, channel, objectId, subscription);
        }

        if (objectId != eObjectId.OBJ_ControlDevice.getValue()) {
            log.error("SubscriptionRegisterService.response: {}, Unknown ObjectId: {}, Subscription: {}", ipAddress, objectId, subscription.toString());
            return false;
        }

        try {
            Registered registered = null;
            int subscribeSerialNbr = subscription.getDatexSubscribeSerialNbr().value.intValue();
            SubscriptionData subscriptionData = subscription.getDatexSubscribeType().getSubscription();

            if (subscriptionData.getDatexSubscribeMode().getEventDriven() != null) {
                registered = subscriptionData.getDatexSubscribeMode().getEventDriven();
                log.info("SubscriptionRegisterService.response: {}. EventDriven. subscribeSerialNbr: {}", ipAddress, subscribeSerialNbr);
            }
            else if (subscriptionData.getDatexSubscribeMode().getPeriodic() != null) {
                registered = subscriptionData.getDatexSubscribeMode().getPeriodic();
                log.info("SubscriptionRegisterService.response: {}. Periodic. subscribeSerialNbr: {}", ipAddress, subscribeSerialNbr);
            }

            if (registered != null) {
                // 필요하면 목록에 저장하고 있다가 스케쥴러에 의해 수행될수 있도록 하자.
                // 서버 모드에서는 특별히 처리할 게 없다.
                ByteArrayInputStream berInputStream = new ByteArrayInputStream(subscriptionData.getDatexSubscribePdu().getEndApplicationMessageMsg().value);
                ControlDeviceList devices = new ControlDeviceList();
                devices.decode(berInputStream);
                List<ControlDevice> list = devices.getControlDevice();
                for (ControlDevice controlDevice : list) {
                    if (controlDevice.getVpbdControlDeviceData() != null) {
                        eControlDevice e = eControlDevice.getByValue(controlDevice.getVpbdControlID().value[0]);
                        log.info("SubscriptionRegisterService.response: {}", e.toString());
                        switch(e) {
                            case Control_Command:        //(0x01, "Control_Command"),
                                break;
                            case Control_BasicInfo:      //(0x02, "Control_BasicInfo"),
                                break;
                            case Control_StatusRequest:  //(0x03, "Control_StatusRequest"),
                                ControlDeviceService.getInstance().decoding_ControlDevice_Status_ITTelecom(obj, controlDevice);
                                break;
                            case Control_InfoRequest:    //(0x04, "Control_InfoRequest"),
                                DSRCTrafficInfoRequest dsrcTrafficInfoRequest = new DSRCTrafficInfoRequest();
                                ByteArrayInputStream deviceStream = new ByteArrayInputStream(controlDevice.getVpbdControlDeviceData().value);
                                dsrcTrafficInfoRequest.decode(deviceStream);
                                log.info("SubscriptionRegisterService.response: {}", dsrcTrafficInfoRequest.toString());
                                break;
                            case Control_EnterDirInfo:   //(0x05, "Control_EnterDirInfo"),
                                break;
                            case Control_DisconnectInfo: //(0x06, "Control_DisconnectInfo");
                                break;
                        }
                    }
                }
            }
        }
        catch(Exception e) {
            log.error("SubscriptionRegisterService.response: {}, Exception: {}", ipAddress, e.toString());
        }
        return true;
    }

    private boolean multiMediaDataResponse(TbRseCtlr obj, Channel channel, int objectId, Subscription subscription) {
        String ipAddress = NettyUtils.getRemoteIpAddress(channel);
        if (objectId != eObjectId.OBJ_MultiMediaData.getValue()) {
            log.error("SubscriptionRegisterService.multiMediaDataResponse: {}, OBJ_MultiMediaData ObjectId: {}, Subscription: {}", ipAddress, objectId, subscription.toString());
            return false;
        }
        try {
            Registered registered = null;
            int subscribeSerialNbr = subscription.getDatexSubscribeSerialNbr().value.intValue();
            SubscriptionData subscriptionData = subscription.getDatexSubscribeType().getSubscription();

            if (subscriptionData.getDatexSubscribeMode().getEventDriven() != null) {
                registered = subscriptionData.getDatexSubscribeMode().getEventDriven();
                //log.info("SubscriptionRegisterService.multiMediaDataResponse: {}. EventDriven. subscribeSerialNbr: {}", ipAddress, subscribeSerialNbr);
            }
            else if (subscriptionData.getDatexSubscribeMode().getPeriodic() != null) {
                registered = subscriptionData.getDatexSubscribeMode().getPeriodic();
                //log.info("SubscriptionRegisterService.multiMediaDataResponse: {}. Periodic. subscribeSerialNbr: {}", ipAddress, subscribeSerialNbr);
            }

            if (registered != null) {
//                ByteArrayInputStream berInputStream = new ByteArrayInputStream(subscriptionData.getDatexSubscribePdu().getEndApplicationMessageMsg().value);
//                MultiMediaDataList dataOrg = new MultiMediaDataList();
//                dataOrg.decode(berInputStream);
//                List<MultiMediaData> dataLists = dataOrg.getMultiMediaData();
//                for (MultiMediaData media : dataLists) {
//                    log.info("{}", media);
//                }
            }
        }
        catch(Exception e) {
            log.error("SubscriptionRegisterService.multiMediaDataResponse: {}, Exception: {}", ipAddress, e.toString());
        }
        return true;
    }
}
