/*
 * 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.Maps;
import org.onlab.util.SharedScheduledExecutors;
import org.onlab.util.Tools;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.event.AbstractListenerManager;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.BngProgrammable;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.pi.runtime.PiCounterCellData;
import org.opencord.bng.BngAttachment;
import org.opencord.bng.BngService;
import org.opencord.bng.BngStatsEvent;
import org.opencord.bng.BngStatsEventListener;
import org.opencord.bng.BngStatsEventSubject;
import org.opencord.bng.BngStatsService;
import org.osgi.service.component.ComponentContext;
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.Modified;
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.Dictionary;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import static org.opencord.bng.impl.OsgiPropertyConstants.BNG_STATISTICS_PROBE_RATE;
import static org.opencord.bng.impl.OsgiPropertyConstants.BNG_STATISTICS_PROBE_RATE_DEFAULT;

@Component(immediate = true,
        property = {
                BNG_STATISTICS_PROBE_RATE + ":Long=" + BNG_STATISTICS_PROBE_RATE_DEFAULT,
        }
)
public class BngStatsManager
        extends AbstractListenerManager<BngStatsEvent, BngStatsEventListener> implements BngStatsService {

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected ComponentConfigService componentConfigService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected BngService bngService;

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

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

    private ApplicationId appId;
    /**
     * The BNG statistics probe rate.
     */
    private long bngStatisticsProbeRate = BNG_STATISTICS_PROBE_RATE_DEFAULT;
    private ScheduledFuture<?> timeout;

    @Activate
    protected void activate() {
        eventDispatcher.addSink(BngStatsEvent.class, listenerRegistry);
        componentConfigService.registerProperties(getClass());
        appId = coreService.getAppId(BngManager.BNG_APP);
        start();
        log.info("BNG Statistics manager activated");
    }

    @Modified
    protected void modified(ComponentContext context) {
        Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
        Long probeRate = Tools.getLongProperty(properties, BNG_STATISTICS_PROBE_RATE);
        if (probeRate != null) {
            bngStatisticsProbeRate = probeRate;
        }
    }

    @Deactivate
    protected void deactivate() {
        shutdown();
        componentConfigService.unregisterProperties(getClass(), false);
        eventDispatcher.removeSink(BngStatsEvent.class);
        log.info("BNG Statistics manager deactivated");

    }

    /**
     * Starts the BNG statistics monitor. Does nothing if the monitor is already
     * running.
     */
    private void start() {
        synchronized (bngStatsMonitor) {
            if (timeout == null) {
                timeout = SharedScheduledExecutors.newTimeout(bngStatsMonitor, 0, TimeUnit.MILLISECONDS);
            }
        }
    }

    /**
     * Stops the BNG statistics monitor.
     */
    private void shutdown() {
        synchronized (bngStatsMonitor) {
            if (timeout != null) {
                timeout.cancel(true);
                timeout = null;
            }
        }
    }

    private Map<String, Map<BngProgrammable.BngCounterType, PiCounterCellData>> getStats(
            Map<String, BngAttachment> attachments) {
        Map<String, Map<BngProgrammable.BngCounterType, PiCounterCellData>>
                stats = Maps.newHashMap();
        attachments.forEach((key, value) -> stats.put(key, getStats(key)));
        return stats;
    }

    @Override
    public Map<BngProgrammable.BngCounterType, PiCounterCellData> getStats(
            String bngAttachmentKey) {
        BngProgrammable bngProgrammable = getBngProgrammable(bngService.getBngDeviceId());
        BngAttachment attachment = bngService.getAttachment(bngAttachmentKey);
        if (bngProgrammable != null && attachment != null) {
            try {
                return bngProgrammable.readCounters(attachment);
            } catch (BngProgrammable.BngProgrammableException e) {
                log.error("Error getting statistics of {}", bngAttachmentKey);
            }
        }
        return Maps.newHashMap();
    }

    @Override
    public PiCounterCellData getControlStats() {
        BngProgrammable bngProgrammable = getBngProgrammable(bngService.getBngDeviceId());
        if (bngProgrammable != null) {
            try {
                return bngProgrammable.readControlTrafficCounter();
            } catch (BngProgrammable.BngProgrammableException e) {
                log.error("Error control plane packets statistics");
            }
        }
        return null;
    }

    private BngProgrammable getBngProgrammable(DeviceId deviceId) {
        if (deviceId != null && deviceService.isAvailable(deviceId)) {
            return deviceService.getDevice(deviceId).as(BngProgrammable.class);
        }
        return null;
    }

    private class BngStatisticsMonitor implements Runnable {
        @Override
        public void run() {
            BngProgrammable bngProgrammable = getBngProgrammable(bngService.getBngDeviceId());
            if (bngProgrammable != null) {
                var attachments = bngService.getAttachments();
                Map<String, Map<BngProgrammable.BngCounterType, PiCounterCellData>>
                        attachmentsStats = getStats(attachments);
                // Create an event for each attachment statistics
                attachmentsStats.forEach((attachmentKey, stats) -> {
                    BngStatsEventSubject evInfo =
                            new BngStatsEventSubject(attachmentKey,
                                                     attachments.get(attachmentKey),
                                                     stats);
                    post(new BngStatsEvent(BngStatsEvent.EventType.STATS_UPDATED, evInfo));
                });
            } else {
                log.debug("BngProgrammable not available");
            }
            synchronized (this) {
                if (timeout != null) {
                    timeout = SharedScheduledExecutors.newTimeout(this, bngStatisticsProbeRate, TimeUnit.MILLISECONDS);
                }
            }
        }
    }
}


