/*
 * Copyright 2015 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.net.statistic.impl;

import com.google.common.base.MoreObjects;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
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.onosproject.cli.Comparators;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTypedFlowEntry;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleEvent;
import org.onosproject.net.flow.FlowRuleListener;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.TypedStoredFlowEntry;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.statistic.DefaultLoad;
import org.onosproject.net.statistic.FlowStatisticService;
import org.onosproject.net.statistic.Load;
import org.onosproject.net.statistic.FlowStatisticStore;
import org.onosproject.net.statistic.SummaryFlowEntryWithLoad;
import org.onosproject.net.statistic.TypedFlowEntryWithLoad;

import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.security.AppGuard.checkPermission;
import static org.slf4j.LoggerFactory.getLogger;
import static org.onosproject.security.AppPermission.Type.*;

/**
 * Provides an implementation of the Flow Statistic Service.
 */
@Component(immediate = true, enabled = true)
@Service
public class FlowStatisticManager implements FlowStatisticService {
    private final Logger log = getLogger(getClass());

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected FlowStatisticStore flowStatisticStore;

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

    private final InternalFlowRuleStatsListener frListener = new InternalFlowRuleStatsListener();

    @Activate
    public void activate() {
        flowRuleService.addListener(frListener);
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        flowRuleService.removeListener(frListener);
        log.info("Stopped");
    }

    @Override
    public Map<ConnectPoint, SummaryFlowEntryWithLoad> loadSummary(Device device) {
        checkPermission(STATISTIC_READ);

        Map<ConnectPoint, SummaryFlowEntryWithLoad> summaryLoad = new TreeMap<>(Comparators.CONNECT_POINT_COMPARATOR);

        if (device == null) {
            return summaryLoad;
        }

        List<Port> ports = new ArrayList<>(deviceService.getPorts(device.id()));

        for (Port port : ports) {
            ConnectPoint cp = new ConnectPoint(device.id(), port.number());
            SummaryFlowEntryWithLoad sfe = loadSummaryPortInternal(cp);
            summaryLoad.put(cp, sfe);
        }

        return summaryLoad;
    }

    @Override
    public SummaryFlowEntryWithLoad loadSummary(Device device, PortNumber pNumber) {
        checkPermission(STATISTIC_READ);

        ConnectPoint cp = new ConnectPoint(device.id(), pNumber);
        return loadSummaryPortInternal(cp);
    }

    @Override
    public Map<ConnectPoint, List<TypedFlowEntryWithLoad>> loadAllByType(Device device,
                                                                  TypedStoredFlowEntry.FlowLiveType liveType,
                                                                  Instruction.Type instType) {
        checkPermission(STATISTIC_READ);

        Map<ConnectPoint, List<TypedFlowEntryWithLoad>> allLoad = new TreeMap<>(Comparators.CONNECT_POINT_COMPARATOR);

        if (device == null) {
            return allLoad;
        }

        List<Port> ports = new ArrayList<>(deviceService.getPorts(device.id()));

        for (Port port : ports) {
            ConnectPoint cp = new ConnectPoint(device.id(), port.number());
            List<TypedFlowEntryWithLoad> tfel = loadAllPortInternal(cp, liveType, instType);
            allLoad.put(cp, tfel);
        }

        return allLoad;
    }

    @Override
    public List<TypedFlowEntryWithLoad> loadAllByType(Device device, PortNumber pNumber,
                                               TypedStoredFlowEntry.FlowLiveType liveType,
                                               Instruction.Type instType) {
        checkPermission(STATISTIC_READ);

        ConnectPoint cp = new ConnectPoint(device.id(), pNumber);
        return loadAllPortInternal(cp, liveType, instType);
    }

    @Override
    public Map<ConnectPoint, List<TypedFlowEntryWithLoad>> loadTopnByType(Device device,
                                                                   TypedStoredFlowEntry.FlowLiveType liveType,
                                                                   Instruction.Type instType,
                                                                   int topn) {
        checkPermission(STATISTIC_READ);

        Map<ConnectPoint, List<TypedFlowEntryWithLoad>> allLoad = new TreeMap<>(Comparators.CONNECT_POINT_COMPARATOR);

        if (device == null) {
            return allLoad;
        }

        List<Port> ports = new ArrayList<>(deviceService.getPorts(device.id()));

        for (Port port : ports) {
            ConnectPoint cp = new ConnectPoint(device.id(), port.number());
            List<TypedFlowEntryWithLoad> tfel = loadTopnPortInternal(cp, liveType, instType, topn);
            allLoad.put(cp, tfel);
        }

        return allLoad;
    }

    @Override
    public List<TypedFlowEntryWithLoad> loadTopnByType(Device device, PortNumber pNumber,
                                                TypedStoredFlowEntry.FlowLiveType liveType,
                                                Instruction.Type instType,
                                                int topn) {
        checkPermission(STATISTIC_READ);

        ConnectPoint cp = new ConnectPoint(device.id(), pNumber);
        return loadTopnPortInternal(cp, liveType, instType, topn);
    }

    private SummaryFlowEntryWithLoad loadSummaryPortInternal(ConnectPoint cp) {
        checkPermission(STATISTIC_READ);

        Set<FlowEntry> currentStats;
        Set<FlowEntry> previousStats;

        TypedStatistics typedStatistics;
        synchronized (flowStatisticStore) {
             currentStats = flowStatisticStore.getCurrentFlowStatistic(cp);
            if (currentStats == null) {
                return new SummaryFlowEntryWithLoad(cp, new DefaultLoad());
            }
            previousStats = flowStatisticStore.getPreviousFlowStatistic(cp);
            if (previousStats == null) {
                return new SummaryFlowEntryWithLoad(cp, new DefaultLoad());
            }
            // copy to local flow entry
            typedStatistics = new TypedStatistics(currentStats, previousStats);

            // Check for validity of this stats data
            checkLoadValidity(currentStats, previousStats);
        }

        // current and previous set is not empty!
        Set<FlowEntry> currentSet = typedStatistics.current();
        Set<FlowEntry> previousSet = typedStatistics.previous();
        Load totalLoad = new DefaultLoad(aggregateBytesSet(currentSet), aggregateBytesSet(previousSet),
                TypedFlowEntryWithLoad.avgPollInterval());

        Map<FlowRule, TypedStoredFlowEntry> currentMap;
        Map<FlowRule, TypedStoredFlowEntry> previousMap;

        currentMap = typedStatistics.currentImmediate();
        previousMap = typedStatistics.previousImmediate();
        Load immediateLoad = new DefaultLoad(aggregateBytesMap(currentMap), aggregateBytesMap(previousMap),
                TypedFlowEntryWithLoad.shortPollInterval());

        currentMap = typedStatistics.currentShort();
        previousMap = typedStatistics.previousShort();
        Load shortLoad = new DefaultLoad(aggregateBytesMap(currentMap), aggregateBytesMap(previousMap),
                TypedFlowEntryWithLoad.shortPollInterval());

        currentMap = typedStatistics.currentMid();
        previousMap = typedStatistics.previousMid();
        Load midLoad = new DefaultLoad(aggregateBytesMap(currentMap), aggregateBytesMap(previousMap),
                TypedFlowEntryWithLoad.midPollInterval());

        currentMap = typedStatistics.currentLong();
        previousMap = typedStatistics.previousLong();
        Load longLoad = new DefaultLoad(aggregateBytesMap(currentMap), aggregateBytesMap(previousMap),
                TypedFlowEntryWithLoad.longPollInterval());

        currentMap = typedStatistics.currentUnknown();
        previousMap = typedStatistics.previousUnknown();
        Load unknownLoad = new DefaultLoad(aggregateBytesMap(currentMap), aggregateBytesMap(previousMap),
                TypedFlowEntryWithLoad.avgPollInterval());

        return new SummaryFlowEntryWithLoad(cp, totalLoad, immediateLoad, shortLoad, midLoad, longLoad, unknownLoad);
    }

    private List<TypedFlowEntryWithLoad> loadAllPortInternal(ConnectPoint cp,
                                                             TypedStoredFlowEntry.FlowLiveType liveType,
                                                             Instruction.Type instType) {
        checkPermission(STATISTIC_READ);

        List<TypedFlowEntryWithLoad> retTfel = new ArrayList<>();

        Set<FlowEntry> currentStats;
        Set<FlowEntry> previousStats;

        TypedStatistics typedStatistics;
        synchronized (flowStatisticStore) {
            currentStats = flowStatisticStore.getCurrentFlowStatistic(cp);
            if (currentStats == null) {
                return retTfel;
            }
            previousStats = flowStatisticStore.getPreviousFlowStatistic(cp);
            if (previousStats == null) {
                return retTfel;
            }
            // copy to local flow entry set
            typedStatistics = new TypedStatistics(currentStats, previousStats);

            // Check for validity of this stats data
            checkLoadValidity(currentStats, previousStats);
        }

        // current and previous set is not empty!
        boolean isAllLiveType = (liveType == null ? true : false); // null is all live type
        boolean isAllInstType = (instType == null ? true : false); // null is all inst type

        Map<FlowRule, TypedStoredFlowEntry> currentMap;
        Map<FlowRule, TypedStoredFlowEntry> previousMap;

        if (isAllLiveType || liveType == TypedStoredFlowEntry.FlowLiveType.IMMEDIATE_FLOW) {
            currentMap = typedStatistics.currentImmediate();
            previousMap = typedStatistics.previousImmediate();

            List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
                    isAllInstType, instType, TypedFlowEntryWithLoad.shortPollInterval());
            if (fel.size() > 0) {
                retTfel.addAll(fel);
            }
        }

        if (isAllLiveType || liveType == TypedStoredFlowEntry.FlowLiveType.SHORT_FLOW) {
            currentMap = typedStatistics.currentShort();
            previousMap = typedStatistics.previousShort();

            List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
                    isAllInstType, instType, TypedFlowEntryWithLoad.shortPollInterval());
            if (fel.size() > 0) {
                retTfel.addAll(fel);
            }
        }

        if (isAllLiveType || liveType == TypedStoredFlowEntry.FlowLiveType.MID_FLOW) {
            currentMap = typedStatistics.currentMid();
            previousMap = typedStatistics.previousMid();

            List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
                    isAllInstType, instType, TypedFlowEntryWithLoad.midPollInterval());
            if (fel.size() > 0) {
                retTfel.addAll(fel);
            }
        }

        if (isAllLiveType || liveType == TypedStoredFlowEntry.FlowLiveType.LONG_FLOW) {
            currentMap = typedStatistics.currentLong();
            previousMap = typedStatistics.previousLong();

            List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
                    isAllInstType, instType, TypedFlowEntryWithLoad.longPollInterval());
            if (fel.size() > 0) {
                retTfel.addAll(fel);
            }
        }

        if (isAllLiveType || liveType == TypedStoredFlowEntry.FlowLiveType.UNKNOWN_FLOW) {
            currentMap = typedStatistics.currentUnknown();
            previousMap = typedStatistics.previousUnknown();

            List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
                    isAllInstType, instType, TypedFlowEntryWithLoad.avgPollInterval());
            if (fel.size() > 0) {
                retTfel.addAll(fel);
            }
        }

        return retTfel;
    }

    private List<TypedFlowEntryWithLoad> typedFlowEntryLoadByInstInternal(ConnectPoint cp,
                                                                      Map<FlowRule, TypedStoredFlowEntry> currentMap,
                                                                      Map<FlowRule, TypedStoredFlowEntry> previousMap,
                                                                      boolean isAllInstType,
                                                                      Instruction.Type instType,
                                                                      int liveTypePollInterval) {
        List<TypedFlowEntryWithLoad> fel = new ArrayList<>();

        for (TypedStoredFlowEntry tfe : currentMap.values()) {
            if (isAllInstType ||
                    tfe.treatment().allInstructions().stream().
                            filter(i -> i.type() == instType).
                            findAny().isPresent()) {
                long currentBytes = tfe.bytes();
                long previousBytes = previousMap.getOrDefault(tfe, new DefaultTypedFlowEntry((FlowRule) tfe)).bytes();
                Load fLoad = new DefaultLoad(currentBytes, previousBytes, liveTypePollInterval);
                fel.add(new TypedFlowEntryWithLoad(cp, tfe, fLoad));
            }
        }

        return fel;
    }

    private List<TypedFlowEntryWithLoad> loadTopnPortInternal(ConnectPoint cp,
                                                             TypedStoredFlowEntry.FlowLiveType liveType,
                                                             Instruction.Type instType,
                                                             int topn) {
        List<TypedFlowEntryWithLoad> fel = loadAllPortInternal(cp, liveType, instType);

        // Sort with descending order of load
        List<TypedFlowEntryWithLoad> tfel =
                fel.stream().sorted(Comparators.TYPEFLOWENTRY_WITHLOAD_COMPARATOR).
                        limit(topn).collect(Collectors.toList());

        return tfel;
    }

    private long aggregateBytesSet(Set<FlowEntry> setFE) {
        return setFE.stream().mapToLong(FlowEntry::bytes).sum();
    }

    private long aggregateBytesMap(Map<FlowRule, TypedStoredFlowEntry> mapFE) {
        return mapFE.values().stream().mapToLong(FlowEntry::bytes).sum();
    }

    /**
     * Internal data class holding two set of typed flow entries.
     */
    private static class TypedStatistics {
        private final ImmutableSet<FlowEntry> currentAll;
        private final ImmutableSet<FlowEntry> previousAll;

        private final Map<FlowRule, TypedStoredFlowEntry> currentImmediate = new HashMap<>();
        private final Map<FlowRule, TypedStoredFlowEntry> previousImmediate = new HashMap<>();

        private final Map<FlowRule, TypedStoredFlowEntry> currentShort = new HashMap<>();
        private final Map<FlowRule, TypedStoredFlowEntry> previousShort = new HashMap<>();

        private final Map<FlowRule, TypedStoredFlowEntry> currentMid = new HashMap<>();
        private final Map<FlowRule, TypedStoredFlowEntry> previousMid = new HashMap<>();

        private final Map<FlowRule, TypedStoredFlowEntry> currentLong = new HashMap<>();
        private final Map<FlowRule, TypedStoredFlowEntry> previousLong = new HashMap<>();

        private final Map<FlowRule, TypedStoredFlowEntry> currentUnknown = new HashMap<>();
        private final Map<FlowRule, TypedStoredFlowEntry> previousUnknown = new HashMap<>();

        public TypedStatistics(Set<FlowEntry> current, Set<FlowEntry> previous) {
            this.currentAll = ImmutableSet.copyOf(checkNotNull(current));
            this.previousAll = ImmutableSet.copyOf(checkNotNull(previous));

            currentAll.forEach(fe -> {
                TypedStoredFlowEntry tfe = TypedFlowEntryWithLoad.newTypedStoredFlowEntry(fe);

                switch (tfe.flowLiveType()) {
                    case IMMEDIATE_FLOW:
                        currentImmediate.put(fe, tfe);
                        break;
                    case SHORT_FLOW:
                        currentShort.put(fe, tfe);
                        break;
                    case MID_FLOW:
                        currentMid.put(fe, tfe);
                        break;
                    case LONG_FLOW:
                        currentLong.put(fe, tfe);
                        break;
                    default:
                        currentUnknown.put(fe, tfe);
                        break;
                }
            });

            previousAll.forEach(fe -> {
                TypedStoredFlowEntry tfe = TypedFlowEntryWithLoad.newTypedStoredFlowEntry(fe);

                switch (tfe.flowLiveType()) {
                    case IMMEDIATE_FLOW:
                        if (currentImmediate.containsKey(fe)) {
                            previousImmediate.put(fe, tfe);
                        } else if (currentShort.containsKey(fe)) {
                            previousShort.put(fe, tfe);
                        } else if (currentMid.containsKey(fe)) {
                            previousMid.put(fe, tfe);
                        } else if (currentLong.containsKey(fe)) {
                            previousLong.put(fe, tfe);
                        } else {
                            previousUnknown.put(fe, tfe);
                        }
                        break;
                    case SHORT_FLOW:
                        if (currentShort.containsKey(fe)) {
                            previousShort.put(fe, tfe);
                        } else if (currentMid.containsKey(fe)) {
                            previousMid.put(fe, tfe);
                        } else if (currentLong.containsKey(fe)) {
                            previousLong.put(fe, tfe);
                        } else {
                            previousUnknown.put(fe, tfe);
                        }
                        break;
                    case MID_FLOW:
                        if (currentMid.containsKey(fe)) {
                            previousMid.put(fe, tfe);
                        } else if (currentLong.containsKey(fe)) {
                            previousLong.put(fe, tfe);
                        } else {
                            previousUnknown.put(fe, tfe);
                        }
                        break;
                    case LONG_FLOW:
                        if (currentLong.containsKey(fe)) {
                            previousLong.put(fe, tfe);
                        } else {
                            previousUnknown.put(fe, tfe);
                        }
                        break;
                    default:
                        previousUnknown.put(fe, tfe);
                        break;
                }
            });
        }

        /**
         * Returns flow entries as the current value.
         *
         * @return flow entries as the current value
         */
        public ImmutableSet<FlowEntry> current() {
            return currentAll;
        }

        /**
         * Returns flow entries as the previous value.
         *
         * @return flow entries as the previous value
         */
        public ImmutableSet<FlowEntry> previous() {
            return previousAll;
        }

        public Map<FlowRule, TypedStoredFlowEntry> currentImmediate() {
            return currentImmediate;
        }
        public Map<FlowRule, TypedStoredFlowEntry> previousImmediate() {
            return previousImmediate;
        }
        public Map<FlowRule, TypedStoredFlowEntry> currentShort() {
            return currentShort;
        }
        public Map<FlowRule, TypedStoredFlowEntry> previousShort() {
            return previousShort;
        }
        public Map<FlowRule, TypedStoredFlowEntry> currentMid() {
            return currentMid;
        }
        public Map<FlowRule, TypedStoredFlowEntry> previousMid() {
            return previousMid;
        }
        public Map<FlowRule, TypedStoredFlowEntry> currentLong() {
            return currentLong;
        }
        public Map<FlowRule, TypedStoredFlowEntry> previousLong() {
            return previousLong;
        }
        public Map<FlowRule, TypedStoredFlowEntry> currentUnknown() {
            return currentUnknown;
        }
        public Map<FlowRule, TypedStoredFlowEntry> previousUnknown() {
            return previousUnknown;
        }

        /**
         * Validates values are not empty.
         *
         * @return false if either of the sets is empty. Otherwise, true.
         */
        public boolean isValid() {
            return !(currentAll.isEmpty() || previousAll.isEmpty());
        }

        @Override
        public int hashCode() {
            return Objects.hash(currentAll, previousAll);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof TypedStatistics)) {
                return false;
            }
            final TypedStatistics other = (TypedStatistics) obj;
            return Objects.equals(this.currentAll, other.currentAll) &&
                    Objects.equals(this.previousAll, other.previousAll);
        }

        @Override
        public String toString() {
            return MoreObjects.toStringHelper(this)
                    .add("current", currentAll)
                    .add("previous", previousAll)
                    .toString();
        }
    }

    private void checkLoadValidity(Set<FlowEntry> current, Set<FlowEntry> previous) {
        current.stream().forEach(c -> {
            FlowEntry f = previous.stream().filter(p -> c.equals(p)).
                    findAny().orElse(null);
            if (f != null && c.bytes() < f.bytes()) {
                log.debug("FlowStatisticManager:checkLoadValidity():" +
                        "Error: " + c + " :Previous bytes=" + f.bytes() +
                        " is larger than current bytes=" + c.bytes() + " !!!");
            }
        });

    }

    /**
     * Creates a predicate that checks the instruction type of a flow entry is the same as
     * the specified instruction type.
     *
     * @param instType instruction type to be checked
     * @return predicate
     */
    private static Predicate<FlowEntry> hasInstructionType(Instruction.Type instType) {
        return new Predicate<FlowEntry>() {
            @Override
            public boolean apply(FlowEntry flowEntry) {
                List<Instruction> allInstructions = flowEntry.treatment().allInstructions();

                return allInstructions.stream().filter(i -> i.type() == instType).findAny().isPresent();
            }
        };
    }

    /**
     * Internal flow rule event listener for FlowStatisticManager.
     */
    private class InternalFlowRuleStatsListener implements FlowRuleListener {

        @Override
        public void event(FlowRuleEvent event) {
            FlowRule rule = event.subject();
            switch (event.type()) {
                case RULE_ADDED:
                    if (rule instanceof FlowEntry) {
                        flowStatisticStore.addFlowStatistic((FlowEntry) rule);
                    }
                    break;
                case RULE_UPDATED:
                    flowStatisticStore.updateFlowStatistic((FlowEntry) rule);
                    break;
                case RULE_ADD_REQUESTED:
                    break;
                case RULE_REMOVE_REQUESTED:
                    break;
                case RULE_REMOVED:
                    flowStatisticStore.removeFlowStatistic(rule);
                    break;
                default:
                    log.warn("Unknown flow rule event {}", event);
            }
        }
    }
}
