/*
 * Copyright 2019-2024 Open Networking Foundation (ONF) and the ONF Contributors
 *
 * 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) {
        Set<HostLocation> hostLocation = Set.of(new HostLocation(oltConnectPoint.deviceId(),
                                                                 oltConnectPoint.port(),
                                                                 System.currentTimeMillis()));
        Set<HostLocation> auxLocation = 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;
        }
    }
}
