/*
 * 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.olt.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

import com.google.common.collect.Maps;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.EthType;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.cluster.NodeId;
import org.onosproject.cluster.RoleInfo;
import org.onosproject.mastership.MastershipInfo;
import org.onosproject.mastership.MastershipListener;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.DeviceId;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.PortNumber;
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.EthTypeCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flowobjective.FilteringObjQueueKey;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.ForwardingObjQueueKey;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.NextObjQueueKey;
import org.onosproject.net.flowobjective.NextObjective;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.meter.MeterId;
import org.onosproject.net.meter.MeterKey;
import org.opencord.olt.AccessDevicePort;
import org.opencord.sadis.BandwidthProfileInformation;
import org.opencord.sadis.UniTagInformation;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ListMultimap;

public class OltFlowTest extends TestBase {
    private OltFlowService oltFlowService;
    AccessDevicePort uniPort1 = new AccessDevicePort(new DefaultPort(olt, PortNumber.portNumber(1), true,
            DefaultAnnotations.builder().set(AnnotationKeys.PORT_NAME, "BBSM00010001-1").build()),
            AccessDevicePort.Type.UNI);
    AccessDevicePort uniPort2 = new AccessDevicePort(new DefaultPort(olt, PortNumber.portNumber(2), true,
            DefaultAnnotations.builder().set(AnnotationKeys.PORT_NAME, "BBSM00010002-1").build()),
            AccessDevicePort.Type.UNI);
    AccessDevicePort nniPort = new AccessDevicePort(new DefaultPort(olt, PortNumber.portNumber(65535), true,
            DefaultAnnotations.builder().set(AnnotationKeys.PORT_NAME, "nni-1048576").build()),
            AccessDevicePort.Type.NNI);

    MacAddress macAddress = MacAddress.valueOf("00:00:00:00:0a:0b");

    UniTagInformation.Builder tagInfoBuilder = new UniTagInformation.Builder();
    UniTagInformation uniTagInfo = tagInfoBuilder.setUniTagMatch(VlanId.vlanId((short) 35))
            .setPonCTag(VlanId.vlanId((short) 33))
            .setPonSTag(VlanId.vlanId((short) 7))
            .setDsPonCTagPriority(0)
            .setUsPonSTagPriority(0)
            .setTechnologyProfileId(64)
            .setDownstreamBandwidthProfile(dsBpId)
            .setUpstreamBandwidthProfile(usBpId)
            .setIsDhcpRequired(true)
            .setIsIgmpRequired(true)
            .build();

    UniTagInformation.Builder tagInfoBuilderNoPcp = new UniTagInformation.Builder();
    UniTagInformation uniTagInfoNoPcp = tagInfoBuilderNoPcp.setUniTagMatch(VlanId.vlanId((short) 35))
            .setPonCTag(VlanId.vlanId((short) 34))
            .setPonSTag(VlanId.vlanId((short) 7))
            .setDsPonCTagPriority(-1)
            .setUsPonSTagPriority(-1)
            .setUsPonCTagPriority(-1)
            .setDsPonSTagPriority(-1)
            .setTechnologyProfileId(64)
            .setDownstreamBandwidthProfile(dsBpId)
            .setUpstreamBandwidthProfile(usBpId)
            .setIsDhcpRequired(true)
            .setIsIgmpRequired(true)
            .build();

    UniTagInformation.Builder tagInfoBuilder2 = new UniTagInformation.Builder();
    UniTagInformation uniTagInfoNoDhcpNoIgmp = tagInfoBuilder2
            .setUniTagMatch(VlanId.vlanId((short) 35))
            .setPonCTag(VlanId.vlanId((short) 33))
            .setPonSTag(VlanId.vlanId((short) 7))
            .setDsPonCTagPriority(0)
            .setUsPonSTagPriority(0)
            .setTechnologyProfileId(64)
            .setDownstreamBandwidthProfile(dsBpId)
            .setUpstreamBandwidthProfile(usBpId)
            .build();

    @Before
    public void setUp() {
        oltFlowService = new OltFlowService();
        oltFlowService.oltMeterService = new MockOltMeterService();
        oltFlowService.flowObjectiveService = new MockOltFlowObjectiveService();
        oltFlowService.mastershipService = new MockMastershipService();
        oltFlowService.sadisService = new MockSadisService();
        oltFlowService.bpService = oltFlowService.sadisService.getBandwidthProfileService();
        oltFlowService.appId = appId;
        oltFlowService.pendingEapolForDevice = Maps.newConcurrentMap();
    }

    @Test
    public void testDhcpFiltering() {
        System.out.println(uniPort1);
        oltFlowService.flowObjectiveService.clearQueue();
        // ensure upstream dhcp traps can be added and removed
        oltFlowService.processDhcpFilteringObjectives(uniPort1,
                usMeterId, null, uniTagInfo,
                true, true, Optional.empty());
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 1;
        oltFlowService.processDhcpFilteringObjectives(uniPort1,
                usMeterId, null, uniTagInfo,
                false, true, Optional.empty());
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 2;

        // Ensure upstream flow has no pcp unless properly specified.
        oltFlowService.processDhcpFilteringObjectives(uniPort2,
                usMeterId, null, uniTagInfoNoPcp,
                true, true, Optional.empty());
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 3;

        // ensure upstream flows are not added if uniTagInfo is missing dhcp requirement
        oltFlowService.processDhcpFilteringObjectives(uniPort1,
                usMeterId, null, uniTagInfoNoDhcpNoIgmp,
                true, true, Optional.empty());
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 3;

        // ensure downstream traps don't succeed without global config for nni ports
        oltFlowService.processDhcpFilteringObjectives(nniPort,
                null, null, null,
                true, false, Optional.empty());
        oltFlowService.processDhcpFilteringObjectives(nniPort,
                null, null, null,
                false, false, Optional.empty());
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 3;
        // do global config for nni ports and now it should succeed
        oltFlowService.enableDhcpOnNni = true;
        oltFlowService.processDhcpFilteringObjectives(nniPort,
                null, null, null,
                true, false, Optional.empty());
        oltFlowService.processDhcpFilteringObjectives(nniPort,
                null, null, null,
                false, false, Optional.empty());
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 5;

        // turn on DHCPv6 and we should get 2 flows
        oltFlowService.enableDhcpV6 = true;
        oltFlowService.processDhcpFilteringObjectives(uniPort1,
                usMeterId, null, uniTagInfo,
                true, true, Optional.empty());
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 7;

        // turn off DHCPv4 and it's only v6
        oltFlowService.enableDhcpV4 = false;
        oltFlowService.processDhcpFilteringObjectives(uniPort1,
                usMeterId, null, uniTagInfo,
                true, true, Optional.empty());
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 8;

        // cleanup
        oltFlowService.flowObjectiveService.clearQueue();
        oltFlowService.enableDhcpV4 = true;
        oltFlowService.enableDhcpV6 = false;
    }

    @Test
    public void testPppoedFiltering() {
        oltFlowService.flowObjectiveService.clearQueue();

        // ensure pppoed traps are not added if global config is off.
        oltFlowService.enablePppoe = false;
        oltFlowService.processPPPoEDFilteringObjectives(uniPort1,
                usMeterId, null, uniTagInfo,
                true, true);
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 0;

        // ensure upstream pppoed traps can be added and removed
        oltFlowService.enablePppoe = true;
        oltFlowService.processPPPoEDFilteringObjectives(uniPort1,
                usMeterId, null, uniTagInfo,
                true, true);
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 1;
        oltFlowService.processPPPoEDFilteringObjectives(uniPort1,
                usMeterId, null, uniTagInfo,
                false, true);
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 2;

        // ensure downstream pppoed traps can be added and removed
        oltFlowService.processPPPoEDFilteringObjectives(nniPort,
                null, null, null,
                true, false);
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 3;
        oltFlowService.processPPPoEDFilteringObjectives(nniPort,
                null, null, null,
                false, false);
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 4;

        // cleanup
        oltFlowService.flowObjectiveService.clearQueue();
    }

    @Test
    public void testIgmpFiltering() {
        oltFlowService.flowObjectiveService.clearQueue();

        // ensure igmp flows can be added and removed
        oltFlowService.processIgmpFilteringObjectives(uniPort1,
                usMeterId, null, uniTagInfo,
                true, true);
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 1;
        oltFlowService.processIgmpFilteringObjectives(uniPort1, usMeterId,
                null, uniTagInfo,
                false, true);
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 2;

        // ensure igmp flow is not added if uniTag has no igmp requirement
        oltFlowService.processIgmpFilteringObjectives(uniPort1,
                usMeterId, null, uniTagInfoNoDhcpNoIgmp,
                true, true);
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 2;

        //ensure igmp flow on NNI fails without global setting
        oltFlowService.processIgmpFilteringObjectives(nniPort,
                null, null, null,
                true, false);
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 2;

        // igmp trap on NNI should succeed with global config
        oltFlowService.enableIgmpOnNni = true;
        oltFlowService.processIgmpFilteringObjectives(nniPort,
                null, null, null,
                true, false);
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives().size() == 3;
        // cleanup
        oltFlowService.flowObjectiveService.clearQueue();

    }

    @Test
    public void testEapolFiltering() {
        addBandwidthProfile(uniTagInfo.getUpstreamBandwidthProfile());
        oltFlowService.enableEapol = true;

        //will install
        oltFlowService.processEapolFilteringObjectives(uniPort1,
                uniTagInfo.getUpstreamBandwidthProfile(), Optional.empty(), new CompletableFuture<>(),
                uniTagInfo.getUniTagMatch(), true);

        //bp profile doesn't exist
        oltFlowService.processEapolFilteringObjectives(uniPort1,
                uniTagInfo.getDownstreamBandwidthProfile(), Optional.empty(), new CompletableFuture<>(),
                uniTagInfo.getUniTagMatch(), true);
    }

    @Test
    public void testLldpFiltering() {
        oltFlowService.processLldpFilteringObjective(nniPort, true);
        oltFlowService.processLldpFilteringObjective(nniPort, false);
    }

    @Test
    public void testNniFiltering() {
        oltFlowService.flowObjectiveService.clearQueue();
        oltFlowService.enableDhcpOnNni = true;
        oltFlowService.enableIgmpOnNni = true;
        oltFlowService.processNniFilteringObjectives(nniPort, true);
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives()
                .size() == 3;
        oltFlowService.processNniFilteringObjectives(nniPort, false);
        assert oltFlowService.flowObjectiveService.getPendingFlowObjectives()
                .size() == 6;
        oltFlowService.flowObjectiveService.clearQueue();
    }

    @Test
    public void testUpBuilder() {
        ForwardingObjective objective =
                oltFlowService.createUpBuilder(nniPort, uniPort1, usMeterId, usMeterId, uniTagInfo).add();
        checkObjective(objective, true);
    }

    @Test
    public void testDownBuilder() {
        ForwardingObjective objective =
                oltFlowService.createDownBuilder(nniPort, uniPort1, dsMeterId, dsMeterId, uniTagInfo,
                        Optional.of(macAddress)).remove();
        checkObjective(objective, false);
    }

    private void checkObjective(ForwardingObjective fwd, boolean upstream) {
        TrafficTreatment treatment = fwd.treatment();

        //check instructions
        Set<Instructions.MeterInstruction> meters = treatment.meters();
        assert !meters.isEmpty();

        Instructions.MetadataInstruction writeMetadata = treatment.writeMetadata();
        assert writeMetadata != null;

        List<Instruction> immediateInstructions = treatment.immediate();
        Optional<Instruction> vlanInstruction = immediateInstructions.stream()
                .filter(i -> i.type() == Instruction.Type.L2MODIFICATION)
                .filter(i -> ((L2ModificationInstruction) i).subtype() ==
                        L2ModificationInstruction.L2SubType.VLAN_PUSH ||
                        ((L2ModificationInstruction) i).subtype() ==
                                L2ModificationInstruction.L2SubType.VLAN_POP)
                .findAny();

        assert vlanInstruction.isPresent();

        //check match criteria
        TrafficSelector selector = fwd.selector();
        assert selector.getCriterion(Criterion.Type.IN_PORT) != null;
        assert selector.getCriterion(Criterion.Type.VLAN_VID) != null;

        if (!upstream) {
            assert selector.getCriterion(Criterion.Type.METADATA) != null;
            assert selector.getCriterion(Criterion.Type.ETH_DST) != null;
        }
    }

    private class MockOltMeterService implements org.opencord.olt.internalapi.AccessDeviceMeterService {
        @Override
        public ImmutableMap<String, Collection<MeterKey>> getBpMeterMappings() {
            return null;
        }

        @Override
        public MeterId getMeterIdFromBpMapping(DeviceId deviceId, String bandwidthProfile) {
            return null;
        }


        @Override
        public ImmutableSet<MeterKey> getProgMeters() {
            return null;
        }

        @Override
        public MeterId createMeter(DeviceId deviceId, BandwidthProfileInformation bpInfo,
                                   CompletableFuture<Object> meterFuture) {
            return usMeterId;
        }

        @Override
        public void removeFromPendingMeters(DeviceId deviceId, BandwidthProfileInformation bwpInfo) {

        }

        @Override
        public boolean checkAndAddPendingMeter(DeviceId deviceId, BandwidthProfileInformation bwpInfo) {
            return false;
        }


        @Override
        public void clearMeters(DeviceId deviceId) {
        }

        @Override
        public void clearDeviceState(DeviceId deviceId) {

        }
    }

    private class MockOltFlowObjectiveService implements org.onosproject.net.flowobjective.FlowObjectiveService {
        List<String> flowObjectives = new ArrayList<>();

        @Override
        public void filter(DeviceId deviceId, FilteringObjective filteringObjective) {
            flowObjectives.add(filteringObjective.toString());
            EthTypeCriterion ethType = (EthTypeCriterion)
                    filterForCriterion(filteringObjective.conditions(), Criterion.Type.ETH_TYPE);

            Instructions.MeterInstruction meter = filteringObjective.meta().metered();
            Instruction writeMetadata = filteringObjective.meta().writeMetadata();
            VlanIdCriterion vlanIdCriterion = (VlanIdCriterion)
                    filterForCriterion(filteringObjective.conditions(), Criterion.Type.VLAN_VID);
            PortCriterion portCriterion = (PortCriterion) filteringObjective.key();

            filteringObjective.meta().allInstructions().forEach(instruction -> {
                if (instruction.type().equals(Instruction.Type.L2MODIFICATION)) {
                    L2ModificationInstruction l2Instruction = (L2ModificationInstruction) instruction;
                    if (l2Instruction.subtype().equals(L2ModificationInstruction.L2SubType.VLAN_PCP)) {
                        //this, given the uniTagInfo we provide, should not be present
                        assert false;
                    }
                }
            });


            if (ethType.ethType().equals(EthType.EtherType.LLDP.ethType()) ||
                    portCriterion.port().equals(nniPort.number())) {
                assert meter == null;
                assert writeMetadata == null;
                assert vlanIdCriterion == null;
            } else {
                assert meter.meterId().equals(usMeterId) || meter.meterId().equals(dsMeterId);
                assert writeMetadata != null;
                assert vlanIdCriterion == null || vlanIdCriterion.vlanId() == uniTagInfo.getUniTagMatch()
                        || vlanIdCriterion.vlanId() == uniTagInfoNoPcp.getUniTagMatch();
            }

        }

        @Override
        public void forward(DeviceId deviceId, ForwardingObjective forwardingObjective) {

        }

        @Override
        public void next(DeviceId deviceId, NextObjective nextObjective) {

        }

        @Override
        public int allocateNextId() {
            return 0;
        }

        @Override
        public void initPolicy(String s) {

        }

        @Override
        public void apply(DeviceId deviceId, Objective objective) {

        }

        @Override
        public Map<Pair<Integer, DeviceId>, List<String>> getNextMappingsChain() {
            return null;
        }

        @Override
        public List<String> getNextMappings() {
            return null;
        }

        @Override
        public List<String> getPendingFlowObjectives() {
            return ImmutableList.copyOf(flowObjectives);
        }

        @Override
        public ListMultimap<FilteringObjQueueKey, Objective> getFilteringObjQueue() {
            return null;
        }

        @Override
        public ListMultimap<ForwardingObjQueueKey, Objective> getForwardingObjQueue() {
            return null;
        }

        @Override
        public ListMultimap<NextObjQueueKey, Objective> getNextObjQueue() {
            return null;
        }

        @Override
        public Map<FilteringObjQueueKey, Objective> getFilteringObjQueueHead() {
            return null;
        }

        @Override
        public Map<ForwardingObjQueueKey, Objective> getForwardingObjQueueHead() {
            return null;
        }

        @Override
        public Map<NextObjQueueKey, Objective> getNextObjQueueHead() {
            return null;
        }

        @Override
        public void clearQueue() {
            flowObjectives.clear();
        }

        private Criterion filterForCriterion(Collection<Criterion> criteria, Criterion.Type type) {
            return criteria.stream()
                    .filter(c -> c.type().equals(type))
                    .limit(1)
                    .findFirst().orElse(null);
        }
    }

    private class MockMastershipService implements org.onosproject.mastership.MastershipService {
        @Override
        public MastershipRole getLocalRole(DeviceId deviceId) {
            return null;
        }

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

        @Override
        public CompletableFuture<MastershipRole> requestRoleFor(DeviceId deviceId) {
            return null;
        }

        @Override
        public CompletableFuture<Void> relinquishMastership(DeviceId deviceId) {
            return null;
        }

        @Override
        public NodeId getMasterFor(DeviceId deviceId) {
            return null;
        }

        @Override
        public RoleInfo getNodesFor(DeviceId deviceId) {
            return null;
        }

        @Override
        public MastershipInfo getMastershipFor(DeviceId deviceId) {
            return null;
        }

        @Override
        public Set<DeviceId> getDevicesOf(NodeId nodeId) {
            return null;
        }

        @Override
        public void addListener(MastershipListener mastershipListener) {

        }

        @Override
        public void removeListener(MastershipListener mastershipListener) {

        }
    }
}
