/*
 * 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.opencord.cordvtn.impl;

import com.google.common.collect.ImmutableSet;
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.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.event.ListenerRegistry;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.basics.SubjectFactories;
import org.onosproject.net.host.HostService;
import org.opencord.cordvtn.api.Constants;
import org.opencord.cordvtn.api.CordVtnConfig;
import org.opencord.cordvtn.api.core.ServiceNetworkAdminService;
import org.opencord.cordvtn.api.core.ServiceNetworkEvent;
import org.opencord.cordvtn.api.core.ServiceNetworkListener;
import org.opencord.cordvtn.api.core.ServiceNetworkService;
import org.opencord.cordvtn.api.core.ServiceNetworkStore;
import org.opencord.cordvtn.api.core.ServiceNetworkStoreDelegate;
import org.opencord.cordvtn.api.net.NetworkId;
import org.opencord.cordvtn.api.net.PortId;
import org.opencord.cordvtn.api.net.ServiceNetwork;
import org.opencord.cordvtn.api.net.ServiceNetwork.DependencyType;
import org.opencord.cordvtn.api.net.ServicePort;
import org.slf4j.Logger;

import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Provides implementation of administering and interfacing service network and port.
 */
@Component(immediate = true)
@Service
public class ServiceNetworkManager extends ListenerRegistry<ServiceNetworkEvent, ServiceNetworkListener>
        implements ServiceNetworkAdminService, ServiceNetworkService {

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

    private static final String MSG_SERVICE_NET  = "Service network %s %s";
    private static final String MSG_SERVICE_PORT = "Service port %s %s";
    private static final String MSG_PROVIDER_NET = "Provider network %s %s";
    private static final String MSG_CREATED = "created";
    private static final String MSG_UPDATED = "updated";
    private static final String MSG_REMOVED = "removed";

    private static final String ERR_NULL_SERVICE_NET  = "Service network cannot be null";
    private static final String ERR_NULL_SERVICE_NET_ID  = "Service network ID cannot be null";
    private static final String ERR_NULL_SERVICE_NET_TYPE  = "Service network type cannot be null";
    private static final String ERR_NULL_SERVICE_PORT = "Service port cannot be null";
    private static final String ERR_NULL_SERVICE_PORT_ID = "Service port ID cannot be null";
    private static final String ERR_NULL_SERVICE_PORT_NET_ID = "Service port network ID cannot be null";

    private static final String ERR_NOT_FOUND = " does not exist";
    private static final String ERR_IN_USE = " still in use";

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigRegistry configRegistry;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected HostService hostService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ServiceNetworkStore snetStore;

    // TODO add cordvtn config service and move this
    private static final Class<CordVtnConfig> CONFIG_CLASS = CordVtnConfig.class;
    private final ConfigFactory configFactory =
            new ConfigFactory<ApplicationId, CordVtnConfig>(
                    SubjectFactories.APP_SUBJECT_FACTORY, CONFIG_CLASS, "cordvtn") {
                @Override
                public CordVtnConfig createConfig() {
                    return new CordVtnConfig();
                }
            };

    private final ServiceNetworkStoreDelegate delegate = new InternalServiceNetworkStoreDelegate();

    @Activate
    protected void activate() {
        coreService.registerApplication(Constants.CORDVTN_APP_ID);
        configRegistry.registerConfigFactory(configFactory);
        snetStore.setDelegate(delegate);
        log.info("Started");
    }

    @Deactivate
    protected void deactivate() {
        configRegistry.unregisterConfigFactory(configFactory);
        snetStore.unsetDelegate(delegate);
        log.info("Stopped");
    }

    @Override
    public void purgeStates() {
        snetStore.clear();
    }

    @Override
    public ServiceNetwork serviceNetwork(NetworkId netId) {
        checkNotNull(netId, ERR_NULL_SERVICE_NET_ID);
        return snetStore.serviceNetwork(netId);
    }

    @Override
    public Set<ServiceNetwork> serviceNetworks() {
        return snetStore.serviceNetworks();
    }

    @Override
    public void createServiceNetwork(ServiceNetwork snet) {
        checkNotNull(snet, ERR_NULL_SERVICE_NET);
        checkNotNull(snet.id(), ERR_NULL_SERVICE_NET_ID);
        checkNotNull(snet.type(), ERR_NULL_SERVICE_NET_TYPE);
        synchronized (this) {
            snet.providers().keySet().forEach(provider -> {
                if (snetStore.serviceNetwork(provider) == null) {
                    final String error = String.format(
                            MSG_PROVIDER_NET, provider.id(), ERR_NOT_FOUND);
                    throw new IllegalStateException(error);
                }
            });
            snetStore.createServiceNetwork(snet);
            log.info(String.format(MSG_SERVICE_NET, snet.name(), MSG_CREATED));
        }
    }

    @Override
    public void updateServiceNetwork(ServiceNetwork snet) {
        checkNotNull(snet, ERR_NULL_SERVICE_NET);
        checkNotNull(snet.id(), ERR_NULL_SERVICE_NET_ID);
        synchronized (this) {
            ServiceNetwork existing = snetStore.serviceNetwork(snet.id());
            if (existing == null) {
                final String error = String.format(
                        MSG_SERVICE_NET, snet.id(), ERR_NOT_FOUND);
                throw new IllegalStateException(error);
            }
            // TODO do not allow service type update if the network in use
            snetStore.updateServiceNetwork(DefaultServiceNetwork.builder(existing, snet).build());
            log.info(String.format(MSG_SERVICE_NET, existing.name(), MSG_UPDATED));
        }
    }

    @Override
    public void removeServiceNetwork(NetworkId netId) {
        checkNotNull(netId, ERR_NULL_SERVICE_NET_ID);
        synchronized (this) {
            if (isNetworkInUse(netId)) {
                final String error = String.format(MSG_SERVICE_NET, netId, ERR_IN_USE);
                throw new IllegalStateException(error);
            }
            // remove dependencies on this network first
            serviceNetworks().stream().filter(n -> isProvider(n, netId)).forEach(n -> {
                Map<NetworkId, DependencyType> newProviders = Maps.newHashMap(n.providers());
                newProviders.remove(netId);
                ServiceNetwork updated = DefaultServiceNetwork.builder(n)
                        .providers(newProviders)
                        .build();
                snetStore.updateServiceNetwork(updated);
            });
            ServiceNetwork snet = snetStore.removeServiceNetwork(netId);
            log.info(String.format(MSG_SERVICE_NET, snet.name(), MSG_REMOVED));
        }
    }

    @Override
    public ServicePort servicePort(PortId portId) {
        checkNotNull(portId, ERR_NULL_SERVICE_PORT_ID);
        return snetStore.servicePort(portId);
    }

    @Override
    public Set<ServicePort> servicePorts() {
        return snetStore.servicePorts();
    }

    @Override
    public Set<ServicePort> servicePorts(NetworkId netId) {
        Set<ServicePort> sports = snetStore.servicePorts().stream()
                .filter(p -> Objects.equals(p.networkId(), netId))
                .collect(Collectors.toSet());
        return ImmutableSet.copyOf(sports);
    }

    @Override
    public void createServicePort(ServicePort sport) {
        checkNotNull(sport, ERR_NULL_SERVICE_PORT);
        checkNotNull(sport.id(), ERR_NULL_SERVICE_PORT_ID);
        checkNotNull(sport.networkId(), ERR_NULL_SERVICE_PORT_NET_ID);
        synchronized (this) {
            ServiceNetwork existing = snetStore.serviceNetwork(sport.networkId());
            if (existing == null) {
                final String error = String.format(
                        MSG_SERVICE_NET, sport.networkId(), ERR_NOT_FOUND);
                throw new IllegalStateException(error);
            }
            snetStore.createServicePort(sport);
            log.info(String.format(MSG_SERVICE_PORT, sport.id(), MSG_CREATED));
        }
    }

    @Override
    public void updateServicePort(ServicePort sport) {
        checkNotNull(sport, ERR_NULL_SERVICE_PORT);
        checkNotNull(sport.id(), ERR_NULL_SERVICE_PORT_ID);
        synchronized (this) {
            ServicePort existing = snetStore.servicePort(sport.id());
            if (existing == null) {
                final String error = String.format(
                        MSG_SERVICE_PORT, sport.id(), ERR_NOT_FOUND);
                throw new IllegalStateException(error);
            }
            snetStore.updateServicePort(DefaultServicePort.builder(existing, sport).build());
            log.info(String.format(MSG_SERVICE_PORT, sport.id(), MSG_UPDATED));
        }
    }

    @Override
    public void removeServicePort(PortId portId) {
        checkNotNull(portId, ERR_NULL_SERVICE_PORT_ID);
        synchronized (this) {
            if (isPortInUse(portId)) {
                final String error = String.format(MSG_SERVICE_PORT, portId, ERR_IN_USE);
                throw new IllegalStateException(error);
            }
            snetStore.removeServicePort(portId);
            log.info(String.format(MSG_SERVICE_PORT, portId, MSG_REMOVED));
        }
    }

    /**
     * Returns if the given target network is a provider of the given network.
     *
     * @param snet     service network
     * @param targetId target network
     * @return true if the service network is a provider of the target network
     */
    private boolean isProvider(ServiceNetwork snet, NetworkId targetId) {
        checkNotNull(snet);
        return snet.providers().keySet().contains(targetId);
    }

    private boolean isNetworkInUse(NetworkId netId) {
        // TODO use instance service to see if there's running instance for the network
        return !servicePorts(netId).isEmpty();
    }

    private boolean isPortInUse(PortId portId) {
        ServicePort sport = servicePort(portId);
        if (sport == null) {
            final String error = String.format(MSG_SERVICE_PORT, portId, ERR_NOT_FOUND);
            throw new IllegalStateException(error);
        }
        // TODO use instance service to see if there's running instance for the port
        Host host = hostService.getHost(HostId.hostId(sport.mac()));
        return host != null;
    }

    private class InternalServiceNetworkStoreDelegate implements ServiceNetworkStoreDelegate {

        @Override
        public void notify(ServiceNetworkEvent event) {
            if (event != null) {
                log.trace("send service network event {}", event);
                process(event);
            }
        }
    }
}
