/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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.cordmcast.impl;

import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Iterator;

import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.VlanId;
import org.onosproject.TestApplicationId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreServiceAdapter;
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.McastRoute;
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.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.HostId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.NetworkConfigRegistryAdapter;
import org.onosproject.net.config.basics.McastConfig;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
import org.onosproject.net.flowobjective.FlowObjectiveServiceAdapter;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.NextObjective;

import com.google.common.collect.ImmutableMap;
import org.opencord.cordmcast.CordMcastStatisticsEvent;
import org.opencord.cordmcast.CordMcastStatisticsEventListener;
import org.opencord.sadis.BandwidthProfileInformation;
import org.opencord.sadis.BaseInformationService;
import org.opencord.sadis.SadisService;
import org.opencord.sadis.SubscriberAndDeviceInformation;

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

public class McastTestBase {

     // Map to store the forwardingObjective in flowObjectiveService.forward()
     Map<DeviceId, ForwardingObjective> forwardMap = new HashMap<>();
     // Map to store the nextObjective in flowObjectiveService.next()
     Map<DeviceId, NextObjective> nextMap = new HashMap<>();
     // Device configuration
     protected static final DeviceId DEVICE_ID_OF_A = DeviceId.deviceId("of:00000a0a0a0a0a00");
     // Port number
     protected static final PortNumber PORT_A = PortNumber.portNumber(1048576);
     protected static final PortNumber PORT_B = PortNumber.portNumber(16);
     protected static final PortNumber PORT_C = PortNumber.portNumber(24);

     // Connect Point for creating source and sink
     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_A, PORT_B);
     protected static final ConnectPoint CONNECT_POINT_C = new ConnectPoint(DEVICE_ID_OF_A, PORT_C);

     // serial number of the device A
     protected static final String SERIAL_NUMBER_OF_DEVICE_A = "serialNumberOfDevA";
     // Management ip address of the device A
     protected static final Ip4Address MANAGEMENT_IP_OF_A = Ip4Address.valueOf("10.177.125.4");
     //Host id configuration
     protected static final HostId HOST_ID_NONE = HostId.NONE;
     // Source connect point
     protected static final  Set<ConnectPoint> SOURCES_CP = new HashSet<ConnectPoint>(Arrays.asList(CONNECT_POINT_A));
     Map<HostId, Set<ConnectPoint>> sources = ImmutableMap.of(HOST_ID_NONE, SOURCES_CP);

     protected static final IpAddress MULTICAST_IP = IpAddress.valueOf("224.0.0.22");
     protected static final IpAddress SOURCE_IP = IpAddress.valueOf("192.168.1.1");
     // Creating dummy route with IGMP type.
     McastRoute route1 = new McastRoute(SOURCE_IP, MULTICAST_IP, McastRoute.Type.IGMP);

     // Creating empty sink used in prevRoute
     Set<ConnectPoint> sinksCp = new HashSet<ConnectPoint>(Arrays.asList());
     Map<HostId, Set<ConnectPoint>> sinks = ImmutableMap.of(HOST_ID_NONE, sinksCp);

     // Creating empty source
     Set<ConnectPoint> sourceCp = new HashSet<ConnectPoint>(Arrays.asList());
     Map<HostId, Set<ConnectPoint>> emptySource = ImmutableMap.of(HOST_ID_NONE, sourceCp);

     // Flag to check unknown olt device
     boolean knownOltFlag = false;

     // For the tests reduce events period to 1s
     protected static final int EVENT_GENERATION_PERIOD = 1;

     class MockCoreService extends CoreServiceAdapter {
          @Override
          public ApplicationId registerApplication(String name) {
               ApplicationId testApplicationId = TestApplicationId.create("org.opencord.cordmcast");
               return testApplicationId;
          }
     }

     class MockFlowObjectiveService extends FlowObjectiveServiceAdapter {
          @Override
          public void forward(DeviceId deviceId, ForwardingObjective forwardingObjective) {
              synchronized (forwardMap) {
                forwardMap.put(deviceId, forwardingObjective);
                forwardMap.notify();
              }
          }

          @Override
          public void next(DeviceId deviceId, NextObjective nextObjective) {
             nextMap.put(deviceId, nextObjective);
          }
     }

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

    protected class MockSadisService implements SadisService {

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

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

    /**
     * Mocks the McastConfig class to return vlan id value.
     */
    static class MockMcastConfig extends McastConfig {
        @Override
        public VlanId egressVlan() {
            return VlanId.vlanId("4000");
        }

        @Override
        public VlanId egressInnerVlan() {
            return VlanId.NONE;
        }
    }

    /**
     * Mocks the network config registry.
     */
    @SuppressWarnings("unchecked")
    static final class TestNetworkConfigRegistry
            extends NetworkConfigRegistryAdapter {
        @Override
        public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
            McastConfig mcastConfig = new MockMcastConfig();
            return (C) mcastConfig;
        }
    }

    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;
        }
    }

    public static class MockCordMcastStatisticsEventListener implements CordMcastStatisticsEventListener {
        protected List<CordMcastStatisticsEvent> mcastEventList = new ArrayList<CordMcastStatisticsEvent>();

        @Override
        public void event(CordMcastStatisticsEvent event) {
            mcastEventList.add(event);
        }
    }

    private class MockSubService implements BaseInformationService<SubscriberAndDeviceInformation> {
        MockSubscriberAndDeviceInformation deviceA =
                new MockSubscriberAndDeviceInformation(SERIAL_NUMBER_OF_DEVICE_A, MANAGEMENT_IP_OF_A);

        @Override
        public SubscriberAndDeviceInformation get(String id) {
            return SERIAL_NUMBER_OF_DEVICE_A.equals(id) ? deviceA : null;
        }

        @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, Ip4Address ipAddress) {
            this.setId(id);
            this.setIPAddress(ipAddress);
            this.setUplinkPort((int) PORT_A.toLong());
        }
    }

    class MockDeviceService extends DeviceServiceAdapter {

        @Override
        public Device getDevice(DeviceId deviceId) {
            if (DEVICE_ID_OF_A.equals(deviceId)) {
                DefaultAnnotations.Builder annotationsBuilder = DefaultAnnotations.builder()
                        .set(AnnotationKeys.MANAGEMENT_ADDRESS, MANAGEMENT_IP_OF_A.toString());
                SparseAnnotations annotations = annotationsBuilder.build();
                Annotations[] da = {annotations};

                Device deviceA = new DefaultDevice(null, DEVICE_ID_OF_A, Device.Type.OTHER, "", "",
                        "", SERIAL_NUMBER_OF_DEVICE_A, null, da);
                return deviceA;
            } else {
                knownOltFlag = true;
            }
            return null;
        }
    }

     public OutputInstruction outputPort(TrafficTreatment trafficTreatment) {
         List<Instruction> listOfInstructions = trafficTreatment.allInstructions();
         OutputInstruction output = null;
         for (Instruction intruction : listOfInstructions) {
           output = (OutputInstruction) intruction;
         }
         return output;
     }

     public IPCriterion ipAddress(TrafficSelector trafficSelector) {
       Set<Criterion> criterionSet = trafficSelector.criteria();
       Iterator<Criterion> it = criterionSet.iterator();
       IPCriterion ipCriterion = null;
       while (it.hasNext()) {
           Criterion criteria = it.next();
           if (Criterion.Type.IPV4_DST == criteria.type()) {
             ipCriterion = (IPCriterion) criteria;
           }
       }
       return (IPCriterion) ipCriterion;
     }

}
