/*
 * Copyright 2019-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.bng.impl;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.tuple.Pair;
import org.onlab.packet.EthType;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.behaviour.BngProgrammable;
import org.onosproject.net.behaviour.BngProgrammable.BngProgrammableException;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.host.DefaultHostDescription;
import org.onosproject.net.host.HostDescription;
import org.onosproject.net.host.HostProvider;
import org.onosproject.net.host.HostProviderRegistry;
import org.onosproject.net.host.HostProviderService;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.provider.ProviderId;
import org.opencord.bng.BngAttachment;
import org.opencord.bng.BngService;
import org.opencord.bng.PppoeBngAttachment;
import org.opencord.bng.config.BngConfig;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;

/**
 * Implements the network level BNG service API to manage attachments.
 */
@Component(immediate = true)
public class BngManager implements HostProvider, BngService {
    public static final String BNG_APP = "org.opencord.bng";

    private static final ProviderId PROVIDER_ID = new ProviderId("bngapp", BngManager.BNG_APP);

    private final Logger log = LoggerFactory.getLogger(getClass());
    private final AtomicBoolean bnguInitialized = new AtomicBoolean(false);

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected LinkService linkService;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected CoreService coreService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected NetworkConfigRegistry cfgService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected HostProviderRegistry providerRegistry;

    private ConfigFactory<ApplicationId, BngConfig> cfgFactory = new ConfigFactory<>(
            APP_SUBJECT_FACTORY,
            BngConfig.class,
            BngConfig.KEY) {
        @Override
        public BngConfig createConfig() {
            return new BngConfig();
        }
    };
    private BngProgrammable bngProgrammable;
    private DeviceId bngDeviceId;
    private InternalDeviceListener deviceListener;
    private InternalConfigListener cfgListener;
    private HostProviderService hostProviderService;
    // TODO: add support for other attachment type
    private Map<String, Pair<BngAttachment, HostId>> registeredAttachment;
    private ApplicationId appId;

    @Activate
    protected void activate() {
        appId = coreService.registerApplication(BNG_APP);
        hostProviderService = providerRegistry.register(this);
        registeredAttachment = Maps.newHashMap();
        bngProgrammable = null;
        bngDeviceId = null;
        deviceListener = new InternalDeviceListener();
        cfgListener = new InternalConfigListener();
        cfgService.addListener(cfgListener);
        cfgService.registerConfigFactory(cfgFactory);

        // Update the BNG relay configuration
        updateConfig();

        deviceService.addListener(deviceListener);

        log.info("BNG app activated");
    }

    @Deactivate
    protected void deactivate() {
        providerRegistry.unregister(this);
        if (bngProgrammableAvailable()) {
            try {
                bngProgrammable.cleanUp(appId);
            } catch (BngProgrammableException e) {
                log.error("Error cleaning-up the BNG-U, {}", e.getMessage());
            }
        }
        deviceService.removeListener(deviceListener);
        cfgService.removeListener(cfgListener);
        cfgService.unregisterConfigFactory(cfgFactory);
        registeredAttachment = null;
        bnguInitialized.set(false);
        log.info("BNG app deactivated");
    }

    @Override
    public void setupAttachment(String attachmentKey, BngAttachment attachment) {
        // FIXME: the update case is not completely clear. Should the programAttachment method clean up the counters?
        assert attachment.type().equals(BngProgrammable.Attachment.AttachmentType.PPPoE);
        boolean updating = false;
        var alreadyRegAttachment = registeredAttachment.get(attachmentKey);
        if (alreadyRegAttachment == null) {
            log.info("Registering a new attachment: {}", attachment.toString());
        } else if (!attachment.equals(alreadyRegAttachment.getLeft())) {
            log.info("Updating the attachment: {}", attachment.toString());
            updating = true;
        } else {
            log.info("Attachment already registered: {}", attachment.toString());
            return;
        }
        // FIXME: it could register anyway the attachment but do not program it on the BNG-U.
        if (attachment.type() != BngProgrammable.Attachment.AttachmentType.PPPoE) {
            log.warn("Attachment type not supported, rejecting attachment: {}", attachmentKey);
            return;
        }
        var pppoeAttachment = (PppoeBngAttachment) attachment;
        // Retrieve the connect point on the ASG device
        var asgConnectPoint = getAsgConnectPoint(pppoeAttachment.oltConnectPoint()).orElseThrow();
        final HostId hostId = HostId.hostId(attachment.macAddress(), attachment.sTag());
        final HostDescription hostDescription = createHostDescription(
                attachment.cTag(), attachment.sTag(),
                attachment.macAddress(), attachment.ipAddress(),
                asgConnectPoint, pppoeAttachment.oltConnectPoint(), pppoeAttachment.onuSerial());

        // Make sure that bngProgrammable is available and if so that the attachment is connected to the bngProgrammable
        if (bngProgrammableAvailable() && isCorrectlyConnected(asgConnectPoint)) {
            try {
                programAttachment(attachment, hostId, hostDescription, updating);
            } catch (BngProgrammableException ex) {
                log.error("Attachment not created: " + ex.getMessage());
            }
        } else {
            // If the BNG user plane is not available, or the attachment is not connected to
            // the correct BNG user plane, accept anyway the attachment.
            // Check if the attachment is correctly connected to the BNG user plane when that device will show up.
            log.info("BNG user plane not available, attachment accepted but not programmed");
        }
        log.info("PPPoE Attachment created/updated: {}", pppoeAttachment);
        registeredAttachment.put(attachmentKey, Pair.of(pppoeAttachment, hostId));
    }

    private Optional<ConnectPoint> getAsgConnectPoint(ConnectPoint oltConnectPoint) {
        try {
            // Here I suppose that each OLT can be connected to a SINGLE ASG that is BNG user plane capable
            return Optional.of(linkService.getDeviceEgressLinks(oltConnectPoint.deviceId()).stream()
                                       .filter(link -> isBngProgrammable(link.dst().deviceId()))
                                       .map(link -> link.dst())
                                       .collect(Collectors.toList())
                                       .get(0));

        } catch (IndexOutOfBoundsException ex) {
            return Optional.empty();
        }
    }

    /**
     * Setup of an attachment. Before calling this method, make sure that BNG
     * programmable is available.
     *
     * @param attachment
     * @param hostId
     * @param hostDescription
     * @param update
     * @throws BngProgrammableException
     */
    private void programAttachment(BngAttachment attachment, HostId hostId,
                                   HostDescription hostDescription, boolean update)
            throws BngProgrammableException {
        assert bngProgrammableAvailable();
        bngProgrammable.setupAttachment(attachment);
        if (!update) {
            bngProgrammable.resetCounters(attachment);
        }
        // Trigger host creation in ONOS
        hostProviderService.hostDetected(hostId, hostDescription, true);
    }

    /**
     * Create an host description from the attachment information.
     *
     * @param cTag            Vlan C-TAG.
     * @param sTag            Vlan S-TAG.
     * @param hostMac         MAC address of the attachment.
     * @param hostIp          IP address of the attachment.
     * @param asgConnectPoint Attachment connect point from the ASG switch
     *                        perspective.
     * @param oltConnectPoint Attachment connect point from the OLT
     *                        perspective.
     * @param onuSerialNumber ONU Serial Number.
     * @return Host description of the attachment
     */
    private HostDescription createHostDescription(VlanId cTag, VlanId sTag,
                                                  MacAddress hostMac,
                                                  IpAddress hostIp,
                                                  ConnectPoint asgConnectPoint,
                                                  ConnectPoint oltConnectPoint,
                                                  String onuSerialNumber) {
//        FIXME: use auxLocation when ONOS bug is fixed.
//        Set<HostLocation> auxLocation = Set.of(new HostLocation(asgConnectPoint.deviceId(),
//                                                                asgConnectPoint.port(),
//                                                                System.currentTimeMillis()));
//        Set<HostLocation> hostLocation = Set.of(new HostLocation(oltConnectPoint.deviceId(),
//                                                                 oltConnectPoint.port(),
//                                                                 System.currentTimeMillis()));

        Set<HostLocation> hostLocation = Set.of(new HostLocation(asgConnectPoint.deviceId(),
                                                        asgConnectPoint.port(),
                                                        System.currentTimeMillis()));

        var annotations = DefaultAnnotations.builder()
                .set(ONU_ANNOTATION, onuSerialNumber)
                .build();
        Set<IpAddress> ips = hostIp != null
                ? ImmutableSet.of(hostIp) : ImmutableSet.of();
        return new DefaultHostDescription(hostMac, sTag,
                                          hostLocation,
//                                          auxLocation,
                                          ips, cTag, EthType.EtherType.QINQ.ethType(),
                                          false, annotations);
    }

    @Override
    public void removeAttachment(String attachmentKey) {
        assert attachmentKey != null;
        if (!registeredAttachment.containsKey(attachmentKey)) {
            log.info("Attachment cannot be removed if it wasn't registered");
            return;
        }
        var regAttachment = registeredAttachment.get(attachmentKey).getLeft();

        final HostId hostToBeRemoved = HostId.hostId(regAttachment.macAddress(), regAttachment.sTag());
        registeredAttachment.remove(attachmentKey);
        // Try to remove host even if the BNG user plane is not available
        hostProviderService.hostVanished(hostToBeRemoved);
        if (bngProgrammableAvailable()) {
            try {
                bngProgrammable.removeAttachment(regAttachment);
            } catch (BngProgrammableException ex) {
                log.error("Exception when removing the attachment: " + ex.getMessage());
            }
        } else {
            log.info("BNG-U not available!");
        }
        log.info("Attachment {} removed successfully!", regAttachment);
    }


    @Override
    public Map<String, BngAttachment> getAttachments() {
        return Maps.asMap(registeredAttachment.keySet(),
                          key -> registeredAttachment.get(key).getLeft());
    }

    @Override
    public BngAttachment getAttachment(String attachmentKey) {
        return registeredAttachment.getOrDefault(attachmentKey, Pair.of(null, null))
                .getLeft();
    }

    /**
     * Check if the given connect point is part of the BNG user plane device.
     * Before calling this method, make sure that bngProgrammable is available.
     *
     * @param asgConnectPoint The connect point to check
     * @return
     */
    private boolean isCorrectlyConnected(ConnectPoint asgConnectPoint) {
        assert bngProgrammableAvailable();
        return asgConnectPoint.deviceId().equals(bngProgrammable.data().deviceId());
    }

    /**
     * Setup of the BNG user plane device. This method will cleanup the BNG
     * pipeline, initialize it and then submit all the attachment already
     * registered.
     *
     * @param deviceId BNG user plane device ID
     */
    private void setBngDevice(DeviceId deviceId) {
        synchronized (bnguInitialized) {
            if (bnguInitialized.get()) {
                log.debug("BNG-U {} already initialized", deviceId);
                return;
            }
            if (!deviceService.isAvailable(deviceId)) {
                log.info("BNG-U is currently unavailable, skip setup");
                return;
            }
            if (!isBngProgrammable(deviceId)) {
                log.warn("{} is not BNG-U", deviceId);
                return;
            }
            if (bngProgrammable != null && !bngProgrammable.data().deviceId().equals(deviceId)) {
                log.error("Change of the BNG-U while BNG-U device is available is not supported!");
                return;
            }

            bngProgrammable = deviceService.getDevice(deviceId).as(BngProgrammable.class);
            log.info("Setup BNG-U: {}", deviceId);

            // Initialize behavior
            try {
                bngProgrammable.cleanUp(appId);
                bngProgrammable.init(appId);
                // FIXME: we can improve this re-registration, keeping track of which attachment
                //  already has the flow rules submitted in the flow rule subsystem.
                //  In this way we do not need to cleanUp the bngProgrammable every time it come back online.
                //  If there is any already registered attachment, try to re-setup their attachment.
                resubmitRegisteredAttachment();
                bnguInitialized.set(true);
                log.info("BNG-U setup successful!");
            } catch (BngProgrammableException e) {
                log.error("Error setup BNG-U, {}", e.getMessage());
            }
        }
    }

    /**
     * Resubmit all the attachments to the BNG user plane device. Before calling
     * this method, make sure that bngProgrammable is available
     *
     * @throws BngProgrammableException when error in BNG user plane device.
     */
    private void resubmitRegisteredAttachment() throws BngProgrammableException {
        assert bngProgrammableAvailable();
        for (var registeredAttachemnt : registeredAttachment.entrySet()) {
            var attachment = registeredAttachemnt.getValue().getLeft();
            var host = registeredAttachemnt.getValue().getRight();
            var attachentKey = registeredAttachemnt.getKey();
            var asgConnectPoint = getAsgConnectPoint(attachment.oltConnectPoint());
            if (attachment.type() != BngProgrammable.Attachment.AttachmentType.PPPoE) {
                log.info("Unsupported attachment: {}", attachentKey);
                continue;
            }
            if (asgConnectPoint.isPresent() && isCorrectlyConnected(asgConnectPoint.orElseThrow())) {
                HostDescription hostDescription = createHostDescription(
                        attachment.cTag(), attachment.sTag(),
                        attachment.macAddress(), attachment.ipAddress(),
                        asgConnectPoint.orElseThrow(), attachment.oltConnectPoint(),
                        attachment.onuSerial());
                // When resubmitting registered attachment act as the attachment is being setting up.
                programAttachment(attachment, host, hostDescription, false);
            } else {
                log.info("Attachment is not connected to a valid BNG user plane: {}", attachment);
            }
        }
    }

    /**
     * Unset the BNG user plane device. If available it will be cleaned-up.
     */
    private void unsetBngDevice() {
        synchronized (bnguInitialized) {
            if (bngProgrammable != null) {
                log.info("BNG-U cleanup");
                try {
                    bngProgrammable.cleanUp(appId);
                } catch (BngProgrammableException e) {
                    log.error("Error in BNG-U, {}", e.getMessage());
                }
                bngProgrammable = null;
                bnguInitialized.set(false);
            }
        }
    }

    /**
     * Check if the device is registered and is BNG user plane.
     *
     * @param deviceId
     * @return
     */
    private boolean isBngProgrammable(DeviceId deviceId) {
        final Device device = deviceService.getDevice(deviceId);
        return device != null && device.is(BngProgrammable.class);
    }

    /**
     * Check if the BNG user plane is available.
     *
     * @return
     * @throws BngProgrammableException
     */
    private boolean bngProgrammableAvailable() {
        return bngProgrammable != null;
    }

    private void bngUpdateConfig(BngConfig config) {
        if (config.isValid()) {
            bngDeviceId = config.getBnguDeviceId();
            setBngDevice(bngDeviceId);
        }
    }

    @Override
    public DeviceId getBngDeviceId() {
        return bngDeviceId;
    }

    /**
     * Updates BNG app configuration.
     */
    private void updateConfig() {
        BngConfig bngConfig = cfgService.getConfig(appId, BngConfig.class);
        if (bngConfig != null) {
            bngUpdateConfig(bngConfig);
        }
    }

    @Override
    public void triggerProbe(Host host) {
        // Do nothing here
    }

    @Override
    public ProviderId id() {
        return PROVIDER_ID;
    }

    /**
     * React to new devices. The first device recognized to have BNG-U
     * functionality is taken as BNG-U device.
     */
    private class InternalDeviceListener implements DeviceListener {
        @Override
        public void event(DeviceEvent event) {
            DeviceId deviceId = event.subject().id();
            if (deviceId.equals(bngDeviceId)) {
                switch (event.type()) {
                    case DEVICE_ADDED:
                    case DEVICE_UPDATED:
                    case DEVICE_AVAILABILITY_CHANGED:
                        if (deviceService.isAvailable(deviceId)) {
                            log.debug("Event: {}, setting BNG-U", event.type());
                            setBngDevice(deviceId);
                        }
                        break;
                    case DEVICE_REMOVED:
                    case DEVICE_SUSPENDED:
                        unsetBngDevice();
                        break;
                    case PORT_ADDED:
                    case PORT_UPDATED:
                    case PORT_REMOVED:
                    case PORT_STATS_UPDATED:
                        break;
                    default:
                        log.warn("Unknown device event type {}", event.type());
                }
            }
        }
    }


    /**
     * Listener for network config events.
     */
    private class InternalConfigListener implements NetworkConfigListener {
        @Override
        public void event(NetworkConfigEvent event) {
            switch (event.type()) {
                case CONFIG_UPDATED:
                case CONFIG_ADDED:
                    event.config().ifPresent(config -> {
                        bngUpdateConfig((BngConfig) config);
                        log.info("{} updated", config.getClass().getSimpleName());
                    });
                    break;
                case CONFIG_REMOVED:
                    event.prevConfig().ifPresent(config -> {
                        unsetBngDevice();
                        log.info("{} removed", config.getClass().getSimpleName());
                    });
                    break;
                case CONFIG_REGISTERED:
                case CONFIG_UNREGISTERED:
                    break;
                default:
                    log.warn("Unsupported event type {}", event.type());
                    break;
            }
        }

        @Override
        public boolean isRelevant(NetworkConfigEvent event) {
            if (event.configClass().equals(BngConfig.class)) {
                return true;
            }
            log.debug("Ignore irrelevant event class {}", event.configClass().getName());
            return false;
        }
    }
}
