/*
 * 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.store.trivial.impl;

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.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.IntentStore;
import org.onosproject.net.intent.IntentStoreDelegate;
import org.onosproject.net.intent.Key;
import org.onosproject.store.AbstractStore;
import org.slf4j.Logger;

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

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.
 */
@Component(immediate = true)
@Service
public class SimpleIntentStore
        extends AbstractStore<IntentEvent, IntentStoreDelegate>
        implements IntentStore {

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

    private final Map<Key, IntentData> current = Maps.newConcurrentMap();
    private final Map<Key, IntentData> pending = Maps.newConcurrentMap();

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

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

    @Override
    public long getIntentCount() {
        return current.size();
    }

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

    @Override
    public Iterable<IntentData> getIntentData(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 pending.values().stream()
                    .filter(data -> data.version().isOlderThan(time) &&
                            (!localOnly || isMaster(data.key())))
                    .collect(Collectors.toList());

        }
        return Lists.newArrayList(current.values());
    }

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

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

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

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

            if (IntentData.isUpdateAcceptable(currentData, newData)) {
                if (pendingData != null) {
                    if (pendingData.state() == PURGE_REQ) {
                        current.remove(newData.key(), newData);
                    } else {
                        current.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)
                        pending.remove(newData.key());
                    }
                }
                notifyDelegateIfNotNull(IntentEvent.getEvent(newData));
            }
        }
    }

    private void notifyDelegateIfNotNull(IntentEvent event) {
        if (event != null) {
            notifyDelegate(event);
        }
    }

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

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

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

    @Override
    public void addPending(IntentData data) {
        if (data.version() == null) { // recompiled intents will already have a version
            data.setVersion(new SystemClockTimestamp());
        }
        synchronized (this) {
            IntentData existingData = pending.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) {
                pending.put(data.key(), data);
                checkNotNull(delegate, "Store delegate is not set")
                        .process(data);
                notifyDelegateIfNotNull(IntentEvent.getEvent(data));
            } else {
                log.debug("IntentData {} is older than existing: {}",
                          data, existingData);
            }
            //TODO consider also checking the current map at this point
        }
    }

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

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

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

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