/*
 * Copyright 2017-2023 Open Networking Foundation (ONF) and the ONF Contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.opencord.igmpproxy.impl;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IGMP;
import org.onlab.packet.IGMPMembership;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.cfg.ConfigProperty;
import org.onosproject.cluster.Leader;
import org.onosproject.cluster.Leadership;
import org.onosproject.cluster.NodeId;
import org.onosproject.core.ApplicationId;
import org.onosproject.event.DefaultEventSinkRegistry;
import org.onosproject.event.Event;
import org.onosproject.event.EventDeliveryService;
import org.onosproject.event.EventSink;
import org.onosproject.mastership.MastershipServiceAdapter;
import org.onosproject.mcast.api.McastListener;
import org.onosproject.mcast.api.McastRoute;
import org.onosproject.mcast.api.McastRouteData;
import org.onosproject.mcast.api.MulticastRouteService;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.Annotations;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.HostId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigRegistryAdapter;
import org.onosproject.net.config.basics.McastConfig;
import org.onosproject.net.config.basics.SubjectFactories;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.packet.DefaultInboundPacket;
import org.onosproject.net.packet.DefaultPacketContext;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketServiceAdapter;
import org.opencord.igmpproxy.IgmpLeadershipService;
import org.opencord.igmpproxy.impl.store.groupmember.AbstractGroupMemberStore;
import org.opencord.igmpproxy.impl.store.machine.AbstractStateMachineStore;
import org.opencord.igmpproxy.statemachine.StateMachine;
import org.opencord.igmpproxy.statemachine.StateMachineId;
import org.opencord.sadis.BandwidthProfileInformation;
import org.opencord.sadis.BaseInformationService;
import org.opencord.sadis.SadisService;
import org.opencord.sadis.SubscriberAndDeviceInformation;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.ComponentInstance;

import static com.google.common.base.Preconditions.checkState;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

public class IgmpManagerBase {

    // Device configuration
    protected static final DeviceId DEVICE_ID_OF_A = DeviceId.deviceId("of:1");
    protected static final DeviceId DEVICE_ID_OF_B = DeviceId.deviceId("of:2");
    protected static final DeviceId DEVICE_ID_OF_C = DeviceId.deviceId("of:00000000000000003");

    //Multicast ip address
    protected static final Ip4Address GROUP_IP = Ip4Address.valueOf("224.0.0.0");
    //Unknown group Ip address
    protected static final Ip4Address UNKNOWN_GRP_IP = Ip4Address.valueOf("124.0.0.0");
    // Source ip address of two different device.
    protected static final Ip4Address SOURCE_IP_OF_A = Ip4Address.valueOf("10.177.125.4");
    protected static final Ip4Address SOURCE_IP_OF_B = Ip4Address.valueOf("10.177.125.5");

    // Common connect point of aggregation switch used by all devices.
    protected static final ConnectPoint COMMON_CONNECT_POINT =
            ConnectPoint.deviceConnectPoint("of:00000000000000003/3");
    // Uplink ports for two olts A and B
    protected static final PortNumber PORT_A = PortNumber.portNumber(1);
    protected static final PortNumber PORT_B = PortNumber.portNumber(2);
    protected static final PortNumber PORT_C = PortNumber.portNumber(3);
    protected static final PortNumber PORT_NNI = PortNumber.portNumber(65536);

    // Connect Point mode for two olts
    protected static final ConnectPoint CONNECT_POINT_A = new ConnectPoint(DEVICE_ID_OF_A, PORT_A);
    protected static final ConnectPoint CONNECT_POINT_B = new ConnectPoint(DEVICE_ID_OF_B, PORT_B);
    protected static final ConnectPoint CONNECT_POINT_C = new ConnectPoint(DEVICE_ID_OF_C, PORT_C);

    protected static final String CLIENT_NAS_PORT_ID = "PON 1/1";
    protected static final String CLIENT_CIRCUIT_ID = "CIR-PON 1/1";
    protected String dsBpId = "HSIA-DS";

    private static final int STATISTICS_GEN_PERIOD_IN_SEC = 2;

    private static final String NNI_PREFIX = "nni";

    protected List<Port> lsPorts = new ArrayList<Port>();
    protected List<Device> lsDevices = new ArrayList<Device>();
    // Flag for adding two different devices in oltData
    protected boolean flagForDevice = true;
    PacketContext context;
    // Flag for sending two different packets
    protected boolean flagForPacket = true;
    // Flag for sending two different packets
    protected boolean flagForQueryPacket = false;
    // Flag to check permission
    boolean flagForPermission = false;
    // List to store the packets emitted
    protected List<OutboundPacket> savedPackets;
    protected PacketProcessor packetProcessor;

    class MockDeviceService extends DeviceServiceAdapter {

        @Override
        public Device getDevice(DeviceId deviceId) {
            if (flagForDevice) {
                DefaultAnnotations.Builder annotationsBuilder = DefaultAnnotations.builder()
                        .set(AnnotationKeys.MANAGEMENT_ADDRESS, SOURCE_IP_OF_A.toString());
                SparseAnnotations annotations = annotationsBuilder.build();
                Annotations[] da = {annotations};
                Device deviceA = new DefaultDevice(null, DEVICE_ID_OF_A, Device.Type.OTHER, "", "", "", "", null, da);
                flagForDevice = false;
                return deviceA;
            } else {
                DefaultAnnotations.Builder annotationsBuilder = DefaultAnnotations.builder()
                        .set(AnnotationKeys.MANAGEMENT_ADDRESS, SOURCE_IP_OF_B.toString());
                SparseAnnotations annotations = annotationsBuilder.build();
                Annotations[] da = {annotations};
                Device deviceB = new DefaultDevice(null, DEVICE_ID_OF_B, Device.Type.OTHER, "", "", "", "", null, da);
                return deviceB;
            }
        }

        @Override
        public List<Port> getPorts(DeviceId deviceId) {
            return lsPorts;
        }

        @Override
        public Iterable<Device> getAvailableDevices() {
            DefaultAnnotations.Builder annotationsBuilder = DefaultAnnotations.builder()
                    .set(AnnotationKeys.MANAGEMENT_ADDRESS, SOURCE_IP_OF_A.toString());
            SparseAnnotations annotations = annotationsBuilder.build();
            Annotations[] da = {annotations};
            Device deviceA = new DefaultDevice(null, DEVICE_ID_OF_C, Device.Type.OTHER, "", "", "", "", null, da);
            lsDevices.add(deviceA);
            return lsDevices;
        }

        @Override
        public Port getPort(DeviceId deviceId, PortNumber portNumber) {
            if (portNumber.equals(PORT_NNI)) {
                DefaultAnnotations.Builder annotationsBuilder = DefaultAnnotations.builder()
                        .set(AnnotationKeys.PORT_NAME, NNI_PREFIX);
                Port nni = new DefaultPort(null, portNumber, true, annotationsBuilder.build());
                return nni;
            }
            return super.getPort(deviceId, portNumber);
        }
    }

    static final Class<IgmpproxyConfig> IGMPPROXY_CONFIG_CLASS = IgmpproxyConfig.class;
    static final Class<IgmpproxySsmTranslateConfig> IGMPPROXY_SSM_CONFIG_CLASS = IgmpproxySsmTranslateConfig.class;
    static final Class<McastConfig> MCAST_CONFIG_CLASS = McastConfig.class;
    ConfigFactory<ApplicationId, IgmpproxyConfig> igmpproxyConfigFactory =
            new ConfigFactory<ApplicationId, IgmpproxyConfig>(
                    SubjectFactories.APP_SUBJECT_FACTORY, IGMPPROXY_CONFIG_CLASS, "igmpproxy") {
                @Override
                public IgmpproxyConfig createConfig() {
                    return new IgmpproxyConfig();
                }
            };

    ConfigFactory<ApplicationId, IgmpproxySsmTranslateConfig> igmpproxySsmConfigFactory =
            new ConfigFactory<ApplicationId, IgmpproxySsmTranslateConfig>(
                    SubjectFactories.APP_SUBJECT_FACTORY, IGMPPROXY_SSM_CONFIG_CLASS, "ssmTranslate", true) {

                @Override
                public IgmpproxySsmTranslateConfig createConfig() {
                    return new IgmpproxySsmTranslateConfig();
                }
            };


    class MockIgmpProxyConfig extends IgmpproxyConfig {
        boolean igmpOnPodBasis = true;

        MockIgmpProxyConfig(boolean igmpFlagValue) {
            igmpOnPodBasis = igmpFlagValue;
        }

        @Override
        public boolean igmpOnPodBasis() {
            return igmpOnPodBasis;
        }

        @Override
        public ConnectPoint getSourceDeviceAndPort() {
            if (flagForPermission) {
                return null;
            }
            return COMMON_CONNECT_POINT;
        }

        @Override
        public ConnectPoint connectPoint() {
            return COMMON_CONNECT_POINT;
        }
    }


    class TestNetworkConfigRegistry extends NetworkConfigRegistryAdapter {
        Boolean igmpOnPodFlag = false;

        TestNetworkConfigRegistry(Boolean igmpFlag) {
            igmpOnPodFlag = igmpFlag;
        }

        @SuppressWarnings("unchecked")
        @Override
        public <S> Set<S> getSubjects(Class<S> subjectClass) {
            if (subjectClass.getName().equalsIgnoreCase("org.onosproject.net.DeviceId")) {
                return (Set<S>) ImmutableSet.of(DEVICE_ID_OF_A, DEVICE_ID_OF_B);
            }
            return null;
        }

        @SuppressWarnings("unchecked")
        @Override
        public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
            if (configClass.getName().equalsIgnoreCase("org.opencord.igmpproxy.impl.IgmpproxyConfig")) {
                IgmpproxyConfig igmpproxyConfig = new MockIgmpProxyConfig(igmpOnPodFlag);
                return (C) igmpproxyConfig;
            } else {
                super.getConfig(subject, configClass);
            }
            return null;
        }
    }


    /**
     * Keeps a reference to the PacketProcessor and saves the OutboundPackets. Adds
     * the emitted packet in savedPackets list
     */
    class MockPacketService extends PacketServiceAdapter {

        public MockPacketService() {
            savedPackets = new LinkedList<>();
        }

        @Override
        public void addProcessor(PacketProcessor processor, int priority) {
            packetProcessor = processor;
        }

        @Override
        public void emit(OutboundPacket packet) {
            synchronized (savedPackets) {
                savedPackets.add(packet);
                savedPackets.notify();
            }
        }
    }

    class TestIgmpLeaderShipService implements IgmpLeadershipService {
        private NodeId nodeId = NodeId.nodeId("test-id");
        private Leader leader = new Leader(nodeId, 0, 0);
        private static final String TEST_TOPIC = "igmp-statistics";

        @Override
        public boolean isLocalLeader(DeviceId deviceId) {
            return true;
        }

        @Override
        public NodeId getLocalNodeId() {
            return nodeId;
        }

        @Override
        public NodeId getLeader(String topic) {
            return nodeId;
        }

        @Override
        public Leadership runForLeadership(String topic) {
            return new Leadership(TEST_TOPIC, leader, Lists.newArrayList(nodeId));
        }

        @Override
        public void withdraw(String topic) {

        }
    }

    class MockMastershipService extends MastershipServiceAdapter {
        @Override
        public boolean isLocalMaster(DeviceId deviceId) {
            return true;
        }
    }

    final class TestMulticastRouteService implements MulticastRouteService {
        @Override
        public void addListener(McastListener listener) {
        }

        @Override
        public void removeListener(McastListener listener) {
        }

        @Override
        public void add(McastRoute route) {
        }

        @Override
        public void remove(McastRoute route) {
        }

        @Override
        public Set<McastRoute> getRoutes() {
            return null;
        }

        @Override
        public Set<McastRoute> getRoute(IpAddress groupIp, IpAddress sourceIp) {
            return null;
        }

        @Override
        public void addSource(McastRoute route, HostId source) {
        }

        @Override
        public void addSources(McastRoute route, HostId hostId, Set<ConnectPoint> connectPoints) {
        }

        @Override
        public void addSources(McastRoute route, Set<ConnectPoint> sources) {

        }

        @Override
        public void removeSources(McastRoute route) {

        }

        @Override
        public void removeSource(McastRoute route, HostId source) {

        }

        @Override
        public void removeSources(McastRoute route, Set<ConnectPoint> sources) {

        }

        @Override
        public void removeSources(McastRoute route, HostId hostId, Set<ConnectPoint> connectPoints) {

        }

        @Override
        public void addSink(McastRoute route, HostId hostId) {

        }

        @Override
        public void addSinks(McastRoute route, HostId hostId, Set<ConnectPoint> connectPoints) {

        }

        @Override
        public void addSinks(McastRoute route, Set<ConnectPoint> sinks) {

        }

        @Override
        public void removeSinks(McastRoute route) {

        }

        @Override
        public void removeSink(McastRoute route, HostId hostId) {

        }

        @Override
        public void removeSinks(McastRoute route, Set<ConnectPoint> sink) {

        }

        @Override
        public McastRouteData routeData(McastRoute route) {
            return null;
        }

        @Override
        public Set<ConnectPoint> sources(McastRoute route) {
            return null;
        }

        @Override
        public Set<ConnectPoint> sources(McastRoute route, HostId hostId) {
            return null;
        }

        @Override
        public Set<ConnectPoint> sinks(McastRoute route) {
            return null;
        }

        @Override
        public Set<ConnectPoint> sinks(McastRoute route, HostId hostId) {
            return null;
        }

        @Override
        public Set<ConnectPoint> nonHostSinks(McastRoute route) {
            return null;
        }

    }


    /**
     * Mocks the DefaultPacketContext.
     */
    final class TestPacketContext extends DefaultPacketContext {
        TestPacketContext(long time, InboundPacket inPkt, OutboundPacket outPkt, boolean block) {
            super(time, inPkt, outPkt, block);
        }

        @Override
        public void send() {
            // We don't send anything out.
        }
    }

    /**
     * Sends Ethernet packet to the process method of the Packet Processor.
     *
     * @param reply Ethernet packet
     * @throws InterruptedException
     */
    void sendPacket(Ethernet reply) {

        if (reply != null) {
            final ByteBuffer byteBuffer = ByteBuffer.wrap(reply.serialize());

            if (flagForQueryPacket) {
                InboundPacket inBoundPacket = new DefaultInboundPacket(CONNECT_POINT_C, reply, byteBuffer);
                context = new TestPacketContext(127L, inBoundPacket, null, false);
                packetProcessor.process(context);
            } else {
                if (flagForPacket) {
                    InboundPacket inPacket = new DefaultInboundPacket(CONNECT_POINT_A, reply, byteBuffer);
                    context = new TestPacketContext(127L, inPacket, null, false);
                    flagForPacket = false;

                    packetProcessor.process(context);
                } else {
                    InboundPacket inBoundPacket = new DefaultInboundPacket(CONNECT_POINT_B, reply, byteBuffer);
                    context = new TestPacketContext(127L, inBoundPacket, null, false);
                    flagForPacket = true;

                    packetProcessor.process(context);
                }
            }
        }
    }

    protected class MockSadisService implements SadisService {

        @Override
        public BaseInformationService<SubscriberAndDeviceInformation> getSubscriberInfoService() {
            return new MockSubService();
        }

        @Override
        public BaseInformationService<BandwidthProfileInformation> getBandwidthProfileService() {
            return new MockBpService();
        }
    }

    private class MockBpService implements BaseInformationService<BandwidthProfileInformation> {

        @Override
        public void clearLocalData() {

        }

        @Override
        public void invalidateAll() {

        }

        @Override
        public void invalidateId(String id) {

        }

        @Override
        public BandwidthProfileInformation get(String id) {
            if (id.equals(dsBpId)) {
                BandwidthProfileInformation bpInfo = new BandwidthProfileInformation();
                bpInfo.setAssuredInformationRate(0);
                bpInfo.setCommittedInformationRate(10000);
                bpInfo.setCommittedBurstSize(1000L);
                bpInfo.setExceededBurstSize(2000L);
                bpInfo.setExceededInformationRate(20000);
                return bpInfo;
            }
            return null;
        }

        @Override
        public BandwidthProfileInformation getfromCache(String id) {
            return null;
        }
    }

    private class MockSubService implements BaseInformationService<SubscriberAndDeviceInformation> {
        MockSubscriberAndDeviceInformation sub =
                new MockSubscriberAndDeviceInformation(CLIENT_NAS_PORT_ID,
                        CLIENT_NAS_PORT_ID, CLIENT_CIRCUIT_ID, null, null);

        @Override
        public SubscriberAndDeviceInformation get(String id) {
            return sub;
        }

        @Override
        public void clearLocalData() {

        }

        @Override
        public void invalidateAll() {
        }

        @Override
        public void invalidateId(String id) {
        }

        @Override
        public SubscriberAndDeviceInformation getfromCache(String id) {
            return null;
        }
    }

    private class MockSubscriberAndDeviceInformation extends SubscriberAndDeviceInformation {

        MockSubscriberAndDeviceInformation(String id, String nasPortId,
                                           String circuitId, MacAddress hardId,
                                           Ip4Address ipAddress) {
            this.setHardwareIdentifier(hardId);
            this.setId(id);
            this.setIPAddress(ipAddress);
            this.setNasPortId(nasPortId);
            this.setCircuitId(circuitId);
            this.setUplinkPort((int) PORT_NNI.toLong());
        }
    }

    protected class MockCfgService implements ComponentConfigService {

        @Override
        public Set<String> getComponentNames() {
            return null;
        }

        @Override
        public void registerProperties(Class<?> componentClass) {

        }

        @Override
        public void unregisterProperties(Class<?> componentClass, boolean clear) {

        }

        @Override
        public Set<ConfigProperty> getProperties(String componentName) {
            return null;
        }

        @Override
        public void setProperty(String componentName, String name, String value) {

        }

        @Override
        public void preSetProperty(String componentName, String name, String value) {

        }

        @Override
        public void preSetProperty(String componentName, String name, String value, boolean override) {

        }

        @Override
        public void unsetProperty(String componentName, String name) {

        }

        @Override
        public ConfigProperty getProperty(String componentName, String attribute) {
            return null;
        }

    }

    public static class TestEventDispatcher extends DefaultEventSinkRegistry implements EventDeliveryService {

        @Override
        @SuppressWarnings("unchecked")
        public synchronized void post(Event event) {
            EventSink sink = getSink(event.getClass());
            checkState(sink != null, "No sink for event %s", event);
            sink.process(event);
        }

        @Override
        public void setDispatchTimeLimit(long millis) {
        }

        @Override
        public long getDispatchTimeLimit() {
            return 0;
        }
    }

    class MockComponentContext implements ComponentContext {

        @Override
        public Dictionary<String, Object> getProperties() {
            Dictionary<String, Object> cfgDict = new Hashtable<String, Object>();
            cfgDict.put("statisticsGenerationPeriodInSeconds", STATISTICS_GEN_PERIOD_IN_SEC);
            return cfgDict;
        }

        @Override
        public Object locateService(String name) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Object locateService(String name, ServiceReference reference) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Object[] locateServices(String name) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public BundleContext getBundleContext() {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Bundle getUsingBundle() {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public ComponentInstance getComponentInstance() {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public void enableComponent(String name) {
            // TODO Auto-generated method stub
        }

        @Override
        public void disableComponent(String name) {
            // TODO Auto-generated method stub
        }

        @Override
        public ServiceReference getServiceReference() {
            // TODO Auto-generated method stub
            return null;
        }
    }

    Ethernet buildWrongIgmpPacket(Ip4Address groupIp, Ip4Address sourceIp) {
        IGMPMembership igmpMembership = new IGMPMembership(groupIp);
        igmpMembership.setRecordType((byte) 0x33);

        return IgmpSender.getInstance().buildIgmpPacket(IGMP.TYPE_IGMPV3_MEMBERSHIP_REPORT, groupIp,
                igmpMembership, sourceIp, false, VlanId.ANY_VALUE, VlanId.NO_VID, IgmpSender.DEFAULT_COS);
    }

    Ethernet buildUnknownIgmpPacket(Ip4Address groupIp, Ip4Address sourceIp) {
        IGMPMembership igmpMembership = new IGMPMembership(groupIp);
        igmpMembership.setRecordType((byte) 0x33);

        return IgmpSender.getInstance().buildIgmpPacket((byte) 0x44, groupIp, igmpMembership, sourceIp, false,
                VlanId.ANY_VALUE, VlanId.NO_VID, IgmpSender.DEFAULT_COS);
    }

    class TestStateMachineStoreService extends AbstractStateMachineStore {
        private static final int DEFAULT_COUNT = 0;
        private Map<StateMachineId, AtomicLong> countsMap;

        public TestStateMachineStoreService(Map<StateMachineId, StateMachine> map) {
            super();
            stateMachineMap = Maps.newConcurrentMap();
            countsMap = Maps.newConcurrentMap();
        }

        @Override
        public long increaseAndGetCounter(StateMachineId stateMachineId) {
            AtomicLong count = countsMap.get(stateMachineId);
            if (count == null) {
                count = new AtomicLong(DEFAULT_COUNT);
                countsMap.put(stateMachineId, count);
            }
            return count.incrementAndGet();
        }

        @Override
        public long decreaseAndGetCounter(StateMachineId stateMachineId) {
            AtomicLong count = countsMap.get(stateMachineId);
            if (count.get() > 0) {
                return count.decrementAndGet();
            } else {
                return count.get();
            }
        }

        @Override
        public boolean removeCounter(StateMachineId stateMachineId) {
            countsMap.remove(stateMachineId);
            return true;
        }

        @Override
        public long getCounter(StateMachineId stateMachineId) {
            return countsMap.get(stateMachineId).get();
        }

    }


    class TestGroupMemberStoreService extends AbstractGroupMemberStore {
        public TestGroupMemberStoreService() {
            super(Maps.newConcurrentMap());
        }
    }
}
