/*
 * 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_NAME = "Service port name 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.id(), ERR_NULL_SERVICE_PORT_NAME);
        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);
            }
        }
    }
}
