/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * 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.cordvtn.impl.service;

import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.opencord.cordvtn.api.Instance;
import org.opencord.cordvtn.api.InstanceHandler;
import org.opencord.cordvtn.impl.CordVtnInstanceHandler;
import org.opencord.cordvtn.impl.CordVtnInstanceManager;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.HostId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleService;
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;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.host.DefaultHostDescription;
import org.onosproject.net.host.HostDescription;
import org.onosproject.xosclient.api.VtnPort;
import org.onosproject.xosclient.api.VtnPortApi;
import org.onosproject.xosclient.api.VtnPortId;
import org.onosproject.xosclient.api.VtnService;
import org.opencord.cordvtn.impl.CordVtnPipeline;

import java.util.Map;
import java.util.Set;

import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.flow.criteria.Criterion.Type.IPV4_DST;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_PUSH;

/**
 * Provides network connectivity for vSG instances.
 */
@Component(immediate = true)
@Service(value = VsgInstanceHandler.class)
public final class VsgInstanceHandler extends CordVtnInstanceHandler implements InstanceHandler {

    private static final String STAG = "stag";
    private static final String VSG_VM = "vsgVm";

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected FlowRuleService flowRuleService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CordVtnInstanceManager instanceManager;

    @Activate
    protected void activate() {
        serviceType = VtnService.ServiceType.VSG;
        eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-vsg", "event-handler"));
        super.activate();
    }

    @Deactivate
    protected void deactivate() {
        super.deactivate();
    }

    @Override
    public void instanceDetected(Instance instance) {
        if (isVsgContainer(instance)) {
            log.info("vSG container detected {}", instance);

            // find vsg vm for this vsg container
            String vsgVmId = instance.getAnnotation(VSG_VM);
            if (Strings.isNullOrEmpty(vsgVmId)) {
                log.warn("Failed to find VSG VM for {}", instance);
                return;
            }

            Instance vsgVm = Instance.of(hostService.getHost(HostId.hostId(vsgVmId)));
            VtnPort vtnPort = getVtnPort(vsgVm);
            if (vtnPort == null || getStag(vtnPort) == null) {
                return;
            }

            populateVsgRules(vsgVm, getStag(vtnPort),
                             nodeManager.dpPort(vsgVm.deviceId()),
                             vtnPort.addressPairs().keySet(),
                             true);

        } else {
            VtnPort vtnPort = getVtnPort(instance);
            if (vtnPort == null || getStag(vtnPort) == null) {
                return;
            }

            vtnPort.addressPairs().entrySet().stream()
                    .forEach(pair -> addVsgContainer(
                            instance,
                            pair.getKey(),
                            pair.getValue(),
                            getStag(vtnPort).toString()
                    ));
            super.instanceDetected(instance);
        }
    }

    @Override
    public void instanceRemoved(Instance instance) {
        if (isVsgContainer(instance)) {
            log.info("vSG container vanished {}", instance);

            // find vsg vm for this vsg container
            String vsgVmId = instance.getAnnotation(VSG_VM);
            if (Strings.isNullOrEmpty(vsgVmId)) {
                log.warn("Failed to find VSG VM for {}", instance);
                return;
            }

            Instance vsgVm = Instance.of(hostService.getHost(HostId.hostId(vsgVmId)));
            VtnPort vtnPort = getVtnPort(vsgVm);
            if (vtnPort == null || getStag(vtnPort) == null) {
                return;
            }

            populateVsgRules(vsgVm, getStag(vtnPort),
                             nodeManager.dpPort(vsgVm.deviceId()),
                             vtnPort.addressPairs().keySet(),
                             false);

        } else {
            // TODO remove vsg vm related rules
            super.instanceRemoved(instance);
        }
    }

    /**
     * Updates set of vSGs in a given vSG VM.
     *
     * @param vsgVmId vsg vm host id
     * @param stag stag
     * @param vsgInstances full set of vsg wan ip and mac address pairs in this vsg vm
     */
    public void updateVsgInstances(HostId vsgVmId, String stag, Map<IpAddress, MacAddress> vsgInstances) {
        if (hostService.getHost(vsgVmId) == null) {
            log.debug("vSG VM {} is not added yet, ignore this update", vsgVmId);
            return;
        }

        Instance vsgVm = Instance.of(hostService.getHost(vsgVmId));
        if (vsgVm == null) {
            log.warn("Failed to find existing vSG VM for STAG: {}", stag);
            return;
        }

        log.info("Updates vSGs in {} with STAG: {}", vsgVm, stag);

        // adds vSGs in the address pair
        vsgInstances.entrySet().stream()
                .filter(addr -> hostService.getHostsByMac(addr.getValue()).isEmpty())
                .forEach(addr -> addVsgContainer(
                        vsgVm,
                        addr.getKey(),
                        addr.getValue(),
                        stag));

        // removes vSGs not listed in the address pair
        hostService.getConnectedHosts(vsgVm.host().location()).stream()
                .filter(host -> !host.mac().equals(vsgVm.mac()))
                .filter(host -> !vsgInstances.values().contains(host.mac()))
                .forEach(host -> {
                    log.info("Removed vSG {}", host.toString());
                    instanceManager.removeInstance(host.id());
                });
    }

    private boolean isVsgContainer(Instance instance) {
        return !Strings.isNullOrEmpty(instance.host().annotations().value(STAG));
    }

    private void addVsgContainer(Instance vsgVm, IpAddress vsgWanIp, MacAddress vsgMac,
                                 String stag) {
        HostId hostId = HostId.hostId(vsgMac);
        DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
                .set(Instance.SERVICE_TYPE, vsgVm.serviceType().toString())
                .set(Instance.SERVICE_ID, vsgVm.serviceId().id())
                .set(Instance.PORT_ID, vsgVm.portId().id())
                .set(Instance.NESTED_INSTANCE, Instance.TRUE)
                .set(STAG, stag)
                .set(VSG_VM, vsgVm.host().id().toString())
                .set(Instance.CREATE_TIME, String.valueOf(System.currentTimeMillis()));

        HostDescription hostDesc = new DefaultHostDescription(
                vsgMac,
                VlanId.NONE,
                vsgVm.host().location(),
                Sets.newHashSet(vsgWanIp),
                annotations.build());

        instanceManager.addInstance(hostId, hostDesc);
    }

    private void populateVsgRules(Instance vsgVm, VlanId stag, PortNumber dpPort,
                                  Set<IpAddress> vsgWanIps, boolean install) {
        // for traffics with s-tag, strip the tag and take through the vSG VM
        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchInPort(dpPort)
                .matchVlanId(stag)
                .build();

        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                .setOutput(vsgVm.portNumber())
                .build();

        FlowRule flowRule = DefaultFlowRule.builder()
                .fromApp(appId)
                .withSelector(selector)
                .withTreatment(treatment)
                .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
                .forDevice(vsgVm.deviceId())
                .forTable(CordVtnPipeline.TABLE_VLAN)
                .makePermanent()
                .build();

        pipeline.processFlowRule(install, flowRule);

        // for traffics with customer vlan, tag with the service vlan based on input port with
        // lower priority to avoid conflict with WAN tag
        selector = DefaultTrafficSelector.builder()
                .matchInPort(vsgVm.portNumber())
                .matchVlanId(stag)
                .build();

        treatment = DefaultTrafficTreatment.builder()
                .setOutput(dpPort)
                .build();

        flowRule = DefaultFlowRule.builder()
                .fromApp(appId)
                .withSelector(selector)
                .withTreatment(treatment)
                .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
                .forDevice(vsgVm.deviceId())
                .forTable(CordVtnPipeline.TABLE_VLAN)
                .makePermanent()
                .build();

        pipeline.processFlowRule(install, flowRule);

        // for traffic coming from WAN, tag 500 and take through the vSG VM
        // based on destination ip
        vsgWanIps.stream().forEach(ip -> {
            TrafficSelector downstream = DefaultTrafficSelector.builder()
                    .matchEthType(Ethernet.TYPE_IPV4)
                    .matchIPDst(ip.toIpPrefix())
                    .build();

            TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
                    .pushVlan()
                    .setVlanId(CordVtnPipeline.VLAN_WAN)
                    .setEthDst(vsgVm.mac())
                    .setOutput(vsgVm.portNumber())
                    .build();

            FlowRule downstreamFlowRule = DefaultFlowRule.builder()
                    .fromApp(appId)
                    .withSelector(downstream)
                    .withTreatment(downstreamTreatment)
                    .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
                    .forDevice(vsgVm.deviceId())
                    .forTable(CordVtnPipeline.TABLE_DST_IP)
                    .makePermanent()
                    .build();

            pipeline.processFlowRule(install, downstreamFlowRule);
        });

        // remove downstream flow rules for the vSG not shown in vsgWanIps
        for (FlowRule rule : flowRuleService.getFlowRulesById(appId)) {
            if (!rule.deviceId().equals(vsgVm.deviceId())) {
                continue;
            }
            PortNumber output = getOutputFromTreatment(rule);
            if (output == null || !output.equals(vsgVm.portNumber()) ||
                    !isVlanPushFromTreatment(rule)) {
                continue;
            }

            IpPrefix dstIp = getDstIpFromSelector(rule);
            if (dstIp != null && !vsgWanIps.contains(dstIp.address())) {
                pipeline.processFlowRule(false, rule);
            }
        }
    }

    private VtnPort getVtnPort(Instance instance) {
        checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
        checkNotNull(xosAccess, XOS_ACCESS_ERROR);

        VtnPortId vtnPortId = instance.portId();
        VtnPortApi portApi = xosClient.getClient(xosAccess).vtnPort();
        VtnPort vtnPort = portApi.vtnPort(vtnPortId, osAccess);
        if (vtnPort == null) {
            log.warn("Failed to get port information of {}", instance);
            return null;
        }
        return vtnPort;
    }

    // TODO get stag from XOS when XOS provides it, extract if from port name for now
    private VlanId getStag(VtnPort vtnPort) {
        checkNotNull(vtnPort);

        String portName = vtnPort.name();
        if (portName != null && portName.startsWith(STAG)) {
            return VlanId.vlanId(portName.split("-")[1]);
        } else {
            return null;
        }
    }

    private PortNumber getOutputFromTreatment(FlowRule flowRule) {
        Instruction instruction = flowRule.treatment().allInstructions().stream()
                .filter(inst -> inst instanceof Instructions.OutputInstruction)
                .findFirst()
                .orElse(null);
        if (instruction == null) {
            return null;
        }
        return ((Instructions.OutputInstruction) instruction).port();
    }

    private IpPrefix getDstIpFromSelector(FlowRule flowRule) {
        Criterion criterion = flowRule.selector().getCriterion(IPV4_DST);
        if (criterion != null && criterion instanceof IPCriterion) {
            IPCriterion ip = (IPCriterion) criterion;
            return ip.ip();
        } else {
            return null;
        }
    }

    private boolean isVlanPushFromTreatment(FlowRule flowRule) {
        Instruction instruction = flowRule.treatment().allInstructions().stream()
                .filter(inst -> inst instanceof L2ModificationInstruction)
                .filter(inst -> ((L2ModificationInstruction) inst).subtype().equals(VLAN_PUSH))
                .findAny()
                .orElse(null);
        return instruction != null;
    }
}
