/*
 * Copyright 2018-present Open Networking Foundation
 *
 * 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.odtn.internal;

import org.onosproject.net.ConnectPoint;
import org.onosproject.net.ElementId;
import org.onosproject.odtn.TapiResolver;
import org.onosproject.odtn.utils.tapi.TapiNepRef;
import org.onosproject.odtn.utils.tapi.TapiNodeRef;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * OSGi Component for ODTN TAPI resolver application.
 */
@Component(immediate = true, service = TapiResolver.class)
public class DefaultTapiResolver implements TapiResolver {

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

    protected TapiDataProducer dataProvider = new DcsBasedTapiDataProducer();

    private List<TapiNodeRef> tapiNodeRefList = new CopyOnWriteArrayList<>();
    private List<TapiNepRef> tapiNepRefList = new CopyOnWriteArrayList<>();

    /**
     * When source (e.g. DCS) is updated, set true
     * When cache update completed successfully, set false
     * <p>
     * This flag takes effect when cache update failed with exception,
     * this remains to be true so the cache update process conducts again
     */
    private Boolean isDirty = false;

    /**
     * When source (e.g. DCS) is updated, set true
     * When cache update started, set false
     * <p>
     * This flag takes effect when source updated during cache updating
     * this forces cache update again at the next request
     */
    private Boolean sourceUpdated = false;

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

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

    @Override
    public boolean hasNodeRef(ElementId deviceId) {
        updateCache();
        return tapiNodeRefList.stream()
                .anyMatch(node -> node.getDeviceId().equals(deviceId));
    }

    @Override
    public boolean hasNepRef(ConnectPoint cp) {
        updateCache();
        return tapiNepRefList.stream()
                .anyMatch(nep -> nep.getConnectPoint().equals(cp));
    }

    @Override
    public boolean hasNepRef(String sipId) {
        updateCache();
        return tapiNepRefList.stream()
                .anyMatch(nep -> nep.getSipId() != null && nep.getSipId().equals(sipId));
    }

    @Override
    public TapiNodeRef getNodeRef(TapiNodeRef nodeRef) throws NoSuchElementException {
        updateCache();
        TapiNodeRef ret = null;
        try {
            ret = tapiNodeRefList.stream()
                    .filter(nodeRef::equals)
                    .findFirst().get();
        } catch (NoSuchElementException e) {
            log.error("Node not found of {}", nodeRef);
            throw e;
        }
        return ret;
    }

    @Override
    public TapiNodeRef getNodeRef(ElementId deviceId) throws NoSuchElementException {
        updateCache();
        TapiNodeRef ret = null;
        try {
            ret = tapiNodeRefList.stream()
                    .filter(node -> node.getDeviceId() != null && node.getDeviceId().equals(deviceId))
                    .findFirst().get();
        } catch (NoSuchElementException e) {
            log.error("Node not found associated with {}", deviceId);
            throw e;
        }
        return ret;
    }

    @Override
    public List<TapiNodeRef> getNodeRefs() {
        updateCache();
        return new ArrayList<>(tapiNodeRefList);
    }

    @Override
    public List<TapiNodeRef> getNodeRefs(Map<String, String> filter) {
        updateCache();
        Stream<TapiNodeRef> filterStream = tapiNodeRefList.stream();
        for (String key : filter.keySet()) {
            filterStream = filterStream.filter(nodeRef -> nodeRef.is(key, filter.get(key)));
        }
        return filterStream.collect(Collectors.toList());
    }

    @Override
    public TapiNepRef getNepRef(TapiNepRef nepRef) throws NoSuchElementException {
        updateCache();
        TapiNepRef ret = null;
        try {
            ret = tapiNepRefList.stream()
                    .filter(nepRef::equals)
                    .findFirst().get();
        } catch (NoSuchElementException e) {
            log.error("Nep not found of {}", nepRef);
            throw e;
        }
        return ret;
    }

    @Override
    public TapiNepRef getNepRef(ConnectPoint cp) throws NoSuchElementException {
        updateCache();
        TapiNepRef ret = null;
        try {
            ret = tapiNepRefList.stream()
                    .filter(nep -> nep.getConnectPoint() != null && nep.getConnectPoint().equals(cp))
                    .findFirst().get();
        } catch (NoSuchElementException e) {
            log.error("Nep not found associated with {}", cp);
            throw e;
        }
        return ret;
    }

    @Override
    public TapiNepRef getNepRef(String sipId) throws NoSuchElementException {
        updateCache();
        TapiNepRef ret = null;
        try {
            ret = tapiNepRefList.stream()
                    .filter(nep -> nep.getSipId() != null && nep.getSipId().equals(sipId))
                    .findFirst().get();
        } catch (NoSuchElementException e) {
            log.error("Nep not found associated with {}", sipId);
            throw e;
        }
        return ret;
    }

    @Override
    public List<TapiNepRef> getNepRefs() {
        updateCache();
        return new ArrayList<>(tapiNepRefList);
    }

    @Override
    public List<TapiNepRef> getNepRefs(Map<String, String> filter) {
        updateCache();
        Stream<TapiNepRef> filterStream = tapiNepRefList.stream();
        for (String key : filter.keySet()) {
            filterStream = filterStream.filter(nepRef -> nepRef.is(key, filter.get(key)));
        }
        return filterStream.collect(Collectors.toList());
    }

    @Override
    public void makeDirty() {
        sourceUpdated = true;
        isDirty = true;
    }

    protected void addNodeRef(TapiNodeRef nodeRef) {
        tapiNodeRefList.add(nodeRef);
        log.info("Nodes: {}", tapiNodeRefList);
    }

    protected void addNepRef(TapiNepRef nepRef) {
        tapiNepRefList.add(nepRef);
        log.info("Neps: {}", tapiNepRefList);
    }

    protected void addNodeRefList(List<TapiNodeRef> nodes) {
        tapiNodeRefList = nodes;
        log.info("Nodes: {}", tapiNodeRefList);
    }

    protected void addNepRefList(List<TapiNepRef> neps) {
        tapiNepRefList = neps;
        log.info("Neps: {}", tapiNepRefList);
    }

    private void updateCache() {
        log.info("Dirty: {}, Source updated: {}", isDirty, sourceUpdated);
        if (isDirty || sourceUpdated) {
            sourceUpdated = false;
            clearCache();
            dataProvider.updateCacheRequest(this);
            log.info("Update completed: {}", tapiNodeRefList);
            isDirty = false;
        }
    }

    private void clearCache() {
        tapiNodeRefList.clear();
        tapiNepRefList.clear();
    }
}
