/*
* 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.onosproject.openstacknetworking.switching;

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.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.openstacknetworking.OpenstackSwitchingService;
import org.onosproject.openstacknetworking.AbstractVmHandler;
import org.onosproject.openstacknode.OpenstackNodeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;
import java.util.Optional;

import static org.onosproject.openstacknetworking.Constants.*;
import static org.onosproject.openstacknetworking.RulePopulatorUtil.buildExtension;


/**
 * Populates switching flow rules.
 */
@Service
@Component(immediate = true)
public final class OpenstackSwitchingManager extends AbstractVmHandler
        implements OpenstackSwitchingService {

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceService deviceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected FlowObjectiveService flowObjectiveService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected OpenstackNodeService nodeService;

    private ApplicationId appId;

    @Activate
    protected void activate() {
        super.activate();
        appId = coreService.registerApplication(SWITCHING_APP_ID);
    }

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

    private void populateSwitchingRules(Host host) {
        populateFlowRulesForTunnelTag(host);
        populateFlowRulesForTrafficToSameCnode(host);
        populateFlowRulesForTrafficToDifferentCnode(host);

        log.debug("Populated switching rule for {}", host);
    }

    private void populateFlowRulesForTunnelTag(Host host) {
        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();

        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
                .matchInPort(host.location().port());

        tBuilder.setTunnelId(Long.valueOf(getVni(host)));

        ForwardingObjective fo = DefaultForwardingObjective.builder()
                .withSelector(sBuilder.build())
                .withTreatment(tBuilder.build())
                .withPriority(TUNNELTAG_RULE_PRIORITY)
                .withFlag(ForwardingObjective.Flag.SPECIFIC)
                .fromApp(appId)
                .add();

        flowObjectiveService.forward(host.location().deviceId(), fo);
    }

    private void populateFlowRulesForTrafficToSameCnode(Host host) {
        //For L2 Switching Case
        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();

        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
                .matchIPDst(getIp(host).toIpPrefix())
                .matchTunnelId(Long.valueOf(getVni(host)));

        tBuilder.setOutput(host.location().port());

        ForwardingObjective fo = DefaultForwardingObjective.builder()
                .withSelector(sBuilder.build())
                .withTreatment(tBuilder.build())
                .withPriority(SWITCHING_RULE_PRIORITY)
                .withFlag(ForwardingObjective.Flag.SPECIFIC)
                .fromApp(appId)
                .add();

        flowObjectiveService.forward(host.location().deviceId(), fo);
    }

    private void populateFlowRulesForTrafficToDifferentCnode(Host host) {
        Ip4Address localVmIp = getIp(host);
        DeviceId localDeviceId = host.location().deviceId();
        Optional<IpAddress> localDataIp = nodeService.dataIp(localDeviceId);

        if (!localDataIp.isPresent()) {
            log.debug("Failed to get data IP for device {}",
                    host.location().deviceId());
            return;
        }

        String vni = getVni(host);
        getVmsInDifferentCnode(host).forEach(remoteVm -> {
            Optional<IpAddress> remoteDataIp = nodeService.dataIp(remoteVm.location().deviceId());
            if (remoteDataIp.isPresent()) {
                setVxLanFlowRule(vni,
                        localDeviceId,
                        remoteDataIp.get().getIp4Address(),
                        getIp(remoteVm));

                setVxLanFlowRule(vni,
                        remoteVm.location().deviceId(),
                        localDataIp.get().getIp4Address(),
                        localVmIp);
            }
        });
    }

    private void setVxLanFlowRule(String vni, DeviceId deviceId, Ip4Address remoteIp,
                                  Ip4Address vmIp) {
        Optional<PortNumber> tunnelPort = nodeService.tunnelPort(deviceId);
        if (!tunnelPort.isPresent()) {
            log.warn("Failed to get tunnel port from {}", deviceId);
            return;
        }

        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();

        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
                .matchTunnelId(Long.parseLong(vni))
                .matchIPDst(vmIp.toIpPrefix());
        tBuilder.extension(buildExtension(deviceService, deviceId, remoteIp), deviceId)
                .setOutput(tunnelPort.get());

        ForwardingObjective fo = DefaultForwardingObjective.builder()
                .withSelector(sBuilder.build())
                .withTreatment(tBuilder.build())
                .withPriority(SWITCHING_RULE_PRIORITY)
                .withFlag(ForwardingObjective.Flag.SPECIFIC)
                .fromApp(appId)
                .add();

        flowObjectiveService.forward(deviceId, fo);
    }

    private void removeSwitchingRules(Host host) {
        removeFlowRuleForTunnelTag(host);
        removeFlowRuleForVMsInSameCnode(host);
        removeFlowRuleForVMsInDiffrentCnode(host);

        log.debug("Removed switching rule for {}", host);
    }

    private void removeFlowRuleForTunnelTag(Host host) {
        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();

        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
                .matchInPort(host.location().port());

        ForwardingObjective fo = DefaultForwardingObjective.builder()
                .withSelector(sBuilder.build())
                .withTreatment(tBuilder.build())
                .withPriority(TUNNELTAG_RULE_PRIORITY)
                .withFlag(ForwardingObjective.Flag.SPECIFIC)
                .fromApp(appId)
                .remove();

        flowObjectiveService.forward(host.location().deviceId(), fo);
    }

    private void removeFlowRuleForVMsInSameCnode(Host host) {
        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
                .matchIPDst(getIp(host).toIpPrefix())
                .matchTunnelId(Long.valueOf(getVni(host)));

        ForwardingObjective fo = DefaultForwardingObjective.builder()
                .withSelector(sBuilder.build())
                .withTreatment(DefaultTrafficTreatment.builder().build())
                .withFlag(ForwardingObjective.Flag.SPECIFIC)
                .withPriority(SWITCHING_RULE_PRIORITY)
                .fromApp(appId)
                .remove();

        flowObjectiveService.forward(host.location().deviceId(), fo);
    }

    private void removeFlowRuleForVMsInDiffrentCnode(Host host) {
        DeviceId deviceId = host.location().deviceId();
        final boolean anyPortRemainedInSameCnode = hostService.getConnectedHosts(deviceId)
                .stream()
                .filter(this::isValidHost)
                .anyMatch(h -> Objects.equals(getVni(h), getVni(host)));

        getVmsInDifferentCnode(host).forEach(h -> {
           removeVxLanFlowRule(h.location().deviceId(), getIp(host), getVni(host));
           if (!anyPortRemainedInSameCnode) {
               removeVxLanFlowRule(deviceId, getIp(h), getVni(host));
           }
       });
    }

    private void removeVxLanFlowRule(DeviceId deviceId, Ip4Address vmIp, String vni) {
        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();

        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
                .matchTunnelId(Long.valueOf(vni))
                .matchIPDst(vmIp.toIpPrefix());

        ForwardingObjective fo = DefaultForwardingObjective.builder()
                .withSelector(sBuilder.build())
                .withTreatment(DefaultTrafficTreatment.builder().build())
                .withFlag(ForwardingObjective.Flag.SPECIFIC)
                .withPriority(SWITCHING_RULE_PRIORITY)
                .fromApp(appId)
                .remove();

        flowObjectiveService.forward(deviceId, fo);
    }

    @Override
    protected void hostDetected(Host host) {
        populateSwitchingRules(host);
        log.info("Added new virtual machine to switching service {}", host);
    }

    @Override
    protected void hostRemoved(Host host) {
        removeSwitchingRules(host);
        log.info("Removed virtual machine from switching service {}", host);
    }

    @Override
    public void reinstallVmFlow(Host host) {
        if (host == null) {
            hostService.getHosts().forEach(h -> {
                populateSwitchingRules(h);
                log.info("Re-Install data plane flow of virtual machine {}", h);
            });
        } else {
            populateSwitchingRules(host);
            log.info("Re-Install data plane flow of virtual machine {}", host);
        }
    }

    @Override
    public void purgeVmFlow(Host host) {
        if (host == null) {
            hostService.getHosts().forEach(h -> {
                removeSwitchingRules(h);
                log.info("Purge data plane flow of virtual machine {}", h);
            });
        } else {
            removeSwitchingRules(host);
            log.info("Purge data plane flow of virtual machine {}", host);
        }
    }
}
