/*
 * Copyright 2017-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.incubator.store.virtual.impl;

import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
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.Service;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.incubator.net.virtual.VirtualNetworkIntentStore;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentData;
import org.onosproject.net.intent.IntentEvent;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.IntentStoreDelegate;
import org.onosproject.net.intent.Key;
import org.onosproject.store.Timestamp;
import org.slf4j.Logger;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.net.intent.IntentState.PURGE_REQ;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Simple single-instance implementation of the intent store for virtual networks.
 */

@Component(immediate = true)
@Service
public class SimpleVirtualIntentStore
        extends AbstractVirtualStore<IntentEvent, IntentStoreDelegate>
        implements VirtualNetworkIntentStore {

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

    private final Map<NetworkId, Map<Key, IntentData>> currentByNetwork =
            Maps.newConcurrentMap();
    private final Map<NetworkId, Map<Key, IntentData>> pendingByNetwork =
            Maps.newConcurrentMap();

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

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


    @Override
    public long getIntentCount(NetworkId networkId) {
        return getCurrentMap(networkId).size();
    }

    @Override
    public Iterable<Intent> getIntents(NetworkId networkId) {
        return getCurrentMap(networkId).values().stream()
                .map(IntentData::intent)
                .collect(Collectors.toList());
    }

    @Override
    public Iterable<IntentData> getIntentData(NetworkId networkId,
                                              boolean localOnly, long olderThan) {
        if (localOnly || olderThan > 0) {
            long older = System.nanoTime() - olderThan * 1_000_000; //convert ms to ns
            final SystemClockTimestamp time = new SystemClockTimestamp(older);
            return getCurrentMap(networkId).values().stream()
                    .filter(data -> data.version().isOlderThan(time) &&
                            (!localOnly || isMaster(networkId, data.key())))
                    .collect(Collectors.toList());
        }
        return Lists.newArrayList(getCurrentMap(networkId).values());
    }

    @Override
    public IntentState getIntentState(NetworkId networkId, Key intentKey) {
        IntentData data = getCurrentMap(networkId).get(intentKey);
        return (data != null) ? data.state() : null;
    }

    @Override
    public List<Intent> getInstallableIntents(NetworkId networkId, Key intentKey) {
        IntentData data = getCurrentMap(networkId).get(intentKey);
        if (data != null) {
            return data.installables();
        }
        return null;
    }

    @Override
    public void write(NetworkId networkId, IntentData newData) {
        checkNotNull(newData);

        synchronized (this) {
            // TODO this could be refactored/cleaned up
            IntentData currentData = getCurrentMap(networkId).get(newData.key());
            IntentData pendingData = getPendingMap(networkId).get(newData.key());

            if (IntentData.isUpdateAcceptable(currentData, newData)) {
                if (pendingData != null) {
                    if (pendingData.state() == PURGE_REQ) {
                        getCurrentMap(networkId).remove(newData.key(), newData);
                    } else {
                        getCurrentMap(networkId).put(newData.key(), new IntentData(newData));
                    }

                    if (pendingData.version().compareTo(newData.version()) <= 0) {
                        // pendingData version is less than or equal to newData's
                        // Note: a new update for this key could be pending (it's version will be greater)
                        getPendingMap(networkId).remove(newData.key());
                    }
                }
                IntentEvent.getEvent(newData).ifPresent(e -> notifyDelegate(networkId, e));
            }
        }
    }

    @Override
    public void batchWrite(NetworkId networkId, Iterable<IntentData> updates) {
        for (IntentData data : updates) {
            write(networkId, data);
        }
    }

    @Override
    public Intent getIntent(NetworkId networkId, Key key) {
        IntentData data = getCurrentMap(networkId).get(key);
        return (data != null) ? data.intent() : null;
    }

    @Override
    public IntentData getIntentData(NetworkId networkId, Key key) {
        IntentData currentData = getCurrentMap(networkId).get(key);
        if (currentData == null) {
            return null;
        }
        return new IntentData(currentData);
    }

    @Override
    public void addPending(NetworkId networkId, IntentData data) {
        if (data.version() == null) { // recompiled intents will already have a version
            data = new IntentData(data.intent(), data.state(), new SystemClockTimestamp());
        }
        synchronized (this) {
            IntentData existingData = getPendingMap(networkId).get(data.key());
            if (existingData == null ||
                    // existing version is strictly less than data's version
                    // Note: if they are equal, we already have the update
                    // TODO maybe we should still make this <= to be safe?
                    existingData.version().compareTo(data.version()) < 0) {
                getPendingMap(networkId).put(data.key(), data);

                checkNotNull(delegateMap.get(networkId), "Store delegate is not set")
                        .process(new IntentData(data));
                IntentEvent.getEvent(data).ifPresent(e -> notifyDelegate(networkId, e));
            } else {
                log.debug("IntentData {} is older than existing: {}",
                          data, existingData);
            }
            //TODO consider also checking the current map at this point
        }
    }

    @Override
    public boolean isMaster(NetworkId networkId, Key intentKey) {
        return true;
    }

    @Override
    public Iterable<Intent> getPending(NetworkId networkId) {
        return getPendingMap(networkId).values().stream()
                .map(IntentData::intent)
                .collect(Collectors.toList());
    }

    @Override
    public Iterable<IntentData> getPendingData(NetworkId networkId) {
        return Lists.newArrayList(getPendingMap(networkId).values());
    }

    @Override
    public IntentData getPendingData(NetworkId networkId, Key intentKey) {
        return getPendingMap(networkId).get(intentKey);
    }

    @Override
    public Iterable<IntentData> getPendingData(NetworkId networkId,
                                               boolean localOnly, long olderThan) {
        long older = System.nanoTime() - olderThan * 1_000_000; //convert ms to ns
        final SystemClockTimestamp time = new SystemClockTimestamp(older);
        return getPendingMap(networkId).values().stream()
                .filter(data -> data.version().isOlderThan(time) &&
                        (!localOnly || isMaster(networkId, data.key())))
                .collect(Collectors.toList());
    }

    /**
     * Returns the current intent map for a specific virtual network.
     *
     * @param networkId a virtual network identifier
     * @return the current map for the requested virtual network
     */
    private Map<Key, IntentData> getCurrentMap(NetworkId networkId) {
        currentByNetwork.computeIfAbsent(networkId,
                                   n -> Maps.newConcurrentMap());
        return currentByNetwork.get(networkId);
    }

    /**
     * Returns the pending intent map for a specific virtual network.
     *
     * @param networkId a virtual network identifier
     * @return the pending intent map for the requested virtual network
     */
    private Map<Key, IntentData> getPendingMap(NetworkId networkId) {
        pendingByNetwork.computeIfAbsent(networkId,
                                   n -> Maps.newConcurrentMap());
        return pendingByNetwork.get(networkId);
    }

    public class SystemClockTimestamp implements Timestamp {

        private final long nanoTimestamp;

        public SystemClockTimestamp() {
            nanoTimestamp = System.nanoTime();
        }

        public SystemClockTimestamp(long timestamp) {
            nanoTimestamp = timestamp;
        }

        @Override
        public int compareTo(Timestamp o) {
            checkArgument(o instanceof SystemClockTimestamp,
                          "Must be SystemClockTimestamp", o);
            SystemClockTimestamp that = (SystemClockTimestamp) o;

            return ComparisonChain.start()
                    .compare(this.nanoTimestamp, that.nanoTimestamp)
                    .result();
        }
    }
}
