/*
 * 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.vtnrsc.floatingip.impl;

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

import java.util.Collection;
import java.util.Collections;
import java.util.Set;

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.onlab.packet.IpAddress;
import org.onlab.util.KryoNamespace;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.onosproject.store.service.EventuallyConsistentMapEvent;
import org.onosproject.store.service.EventuallyConsistentMapListener;
import org.onosproject.store.service.StorageService;
import org.onosproject.store.service.WallClockTimestamp;
import org.onosproject.vtnrsc.DefaultFloatingIp;
import org.onosproject.vtnrsc.FloatingIp;
import org.onosproject.vtnrsc.FloatingIpId;
import org.onosproject.vtnrsc.TenantId;
import org.onosproject.vtnrsc.TenantNetworkId;
import org.onosproject.vtnrsc.VirtualPortId;
import org.onosproject.vtnrsc.RouterId;
import org.onosproject.vtnrsc.floatingip.FloatingIpEvent;
import org.onosproject.vtnrsc.floatingip.FloatingIpListener;
import org.onosproject.vtnrsc.floatingip.FloatingIpService;
import org.onosproject.vtnrsc.router.RouterService;
import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
import org.onosproject.vtnrsc.virtualport.VirtualPortService;
import org.slf4j.Logger;

import com.google.common.collect.Sets;

/**
 * Provides implementation of the FloatingIp service.
 */
@Component(immediate = true)
@Service
public class FloatingIpManager implements FloatingIpService {
    private static final String FLOATINGIP_ID_NOT_NULL = "Floatingip ID cannot be null";
    private static final String FLOATINGIP_NOT_NULL = "Floatingip cannot be null";
    private static final String FLOATINGIPSTORE = "vtn-floatingip-store";
    private static final String FLOATINGIPBINDSTORE = "vtn-floatingip-bind-store";
    private static final String VTNRSC_APP = "org.onosproject.vtnrsc";
    private static final String LISTENER_NOT_NULL = "Listener cannot be null";
    private static final String EVENT_NOT_NULL = "event cannot be null";

    private final Logger log = getLogger(getClass());
    private final Set<FloatingIpListener> listeners = Sets
            .newCopyOnWriteArraySet();
    private EventuallyConsistentMapListener<FloatingIpId, FloatingIp> floatingIpListener =
            new InnerFloatingIpStoreListener();
    protected EventuallyConsistentMap<FloatingIpId, FloatingIp> floatingIpStore;
    protected EventuallyConsistentMap<FloatingIpId, FloatingIp> floatingIpBindStore;
    protected ApplicationId appId;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected StorageService storageService;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected TenantNetworkService tenantNetworkService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected VirtualPortService virtualPortService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected RouterService routerService;

    @Activate
    public void activate() {
        appId = coreService.registerApplication(VTNRSC_APP);
        KryoNamespace.Builder serializer = KryoNamespace
                .newBuilder()
                .register(KryoNamespaces.API)
                .register(FloatingIp.class, FloatingIpId.class,
                          TenantNetworkId.class, TenantId.class,
                          FloatingIp.Status.class, RouterId.class,
                          VirtualPortId.class, DefaultFloatingIp.class);
        floatingIpStore = storageService
                .<FloatingIpId, FloatingIp>eventuallyConsistentMapBuilder()
                .withName(FLOATINGIPSTORE).withSerializer(serializer)
                .withTimestampProvider((k, v) -> new WallClockTimestamp())
                .build();
        floatingIpBindStore = storageService
                .<FloatingIpId, FloatingIp>eventuallyConsistentMapBuilder()
                .withName(FLOATINGIPBINDSTORE).withSerializer(serializer)
                .withTimestampProvider((k, v) -> new WallClockTimestamp())
                .build();
        floatingIpStore.addListener(floatingIpListener);
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        floatingIpStore.removeListener(floatingIpListener);
        floatingIpStore.destroy();
        floatingIpBindStore.destroy();
        listeners.clear();
        log.info("Stopped");
    }

    @Override
    public Collection<FloatingIp> getFloatingIps() {
        return Collections.unmodifiableCollection(floatingIpStore.values());
    }

    @Override
    public FloatingIp getFloatingIp(FloatingIpId floatingIpId) {
        checkNotNull(floatingIpId, FLOATINGIP_ID_NOT_NULL);
        return floatingIpStore.get(floatingIpId);
    }

    @Override
    public boolean exists(FloatingIpId floatingIpId) {
        checkNotNull(floatingIpId, FLOATINGIP_ID_NOT_NULL);
        return floatingIpStore.containsKey(floatingIpId);
    }

    @Override
    public boolean floatingIpIsUsed(IpAddress floatingIpAddr,
                                    FloatingIpId floatingIpId) {
        checkNotNull(floatingIpAddr, "Floating IP address cannot be null");
        checkNotNull(floatingIpId, "Floating IP Id cannot be null");
        Collection<FloatingIp> floatingIps = getFloatingIps();
        for (FloatingIp floatingIp : floatingIps) {
            if (floatingIp.floatingIp().equals(floatingIpAddr)
                    && !floatingIp.id().equals(floatingIpId)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean fixedIpIsUsed(IpAddress fixedIpAddr, TenantId tenantId,
                                 FloatingIpId floatingIpId) {
        checkNotNull(fixedIpAddr, "Fixed IP address cannot be null");
        checkNotNull(tenantId, "Tenant Id cannot be null");
        checkNotNull(floatingIpId, "Floating IP Id cannot be null");
        Collection<FloatingIp> floatingIps = getFloatingIps();
        for (FloatingIp floatingIp : floatingIps) {
            IpAddress fixedIp = floatingIp.fixedIp();
            if (fixedIp != null) {
                if (fixedIp.equals(fixedIpAddr)
                        && floatingIp.tenantId().equals(tenantId)
                        && !floatingIp.id().equals(floatingIpId)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public boolean createFloatingIps(Collection<FloatingIp> floatingIps) {
        checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
        boolean result = true;
        for (FloatingIp floatingIp : floatingIps) {
            verifyFloatingIpData(floatingIp);
            floatingIpStore.put(floatingIp.id(), floatingIp);
            if (!floatingIpStore.containsKey(floatingIp.id())) {
                log.debug("The floating Ip is created failed whose identifier is {}",
                          floatingIp.id().toString());
                result = false;
            }
        }
        return result;
    }

    @Override
    public boolean updateFloatingIps(Collection<FloatingIp> floatingIps) {
        checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
        boolean result = true;
        for (FloatingIp floatingIp : floatingIps) {
            verifyFloatingIpData(floatingIp);
            FloatingIp oldFloatingIp = floatingIpStore.get(floatingIp.id());
            floatingIpBindStore.put(floatingIp.id(), oldFloatingIp);
            floatingIpStore.put(floatingIp.id(), floatingIp);
            if (!floatingIpStore.containsKey(floatingIp.id())) {
                log.debug("The floating Ip is updated failed whose identifier is {}",
                          floatingIp.id().toString());
                result = false;
            }
        }
        return result;
    }

    @Override
    public boolean removeFloatingIps(Collection<FloatingIpId> floatingIpIds) {
        checkNotNull(floatingIpIds, FLOATINGIP_ID_NOT_NULL);
        boolean result = true;
        for (FloatingIpId floatingIpId : floatingIpIds) {
            if (!floatingIpStore.containsKey(floatingIpId)) {
                log.debug("The floatingIp is not exist whose identifier is {}",
                          floatingIpId.toString());
                throw new IllegalArgumentException(
                                                   "FloatingIP ID doesn't exist");
            }
            FloatingIp floatingIp = floatingIpStore.get(floatingIpId);
            floatingIpStore.remove(floatingIpId, floatingIp);
            floatingIpBindStore.remove(floatingIpId);
            if (floatingIpStore.containsKey(floatingIpId)) {
                log.debug("The floating Ip is deleted failed whose identifier is {}",
                          floatingIpId.toString());
                result = false;
            }
        }
        return result;
    }

    @Override
    public void addListener(FloatingIpListener listener) {
        checkNotNull(listener, LISTENER_NOT_NULL);
        listeners.add(listener);
    }

    @Override
    public void removeListener(FloatingIpListener listener) {
        checkNotNull(listener, LISTENER_NOT_NULL);
        listeners.add(listener);
    }

    /**
     * Verifies validity of FloatingIp data.
     *
     * @param floatingIps floatingIp instance
     */
    private void verifyFloatingIpData(FloatingIp floatingIps) {
        checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
        if (!tenantNetworkService.exists(floatingIps.networkId())) {
            log.debug("The network identifier {} that the floating Ip {} create for is not exist",
                      floatingIps.networkId().toString(), floatingIps.id()
                              .toString());
            throw new IllegalArgumentException(
                                               "Floating network ID doesn't exist");
        }

        VirtualPortId portId = floatingIps.portId();
        if (portId != null && !virtualPortService.exists(portId)) {
            log.debug("The port identifier {} that the floating Ip {} create for is not exist",
                      floatingIps.portId().toString(), floatingIps.id()
                              .toString());
            throw new IllegalArgumentException("Port ID doesn't exist");
        }

        RouterId routerId = floatingIps.routerId();
        if (routerId != null && !routerService.exists(routerId)) {
            log.debug("The router identifier {} that the floating Ip {} create for is not exist",
                      floatingIps.routerId().toString(), floatingIps.id()
                              .toString());
            throw new IllegalArgumentException("Router ID doesn't exist");
        }

        if (floatingIpIsUsed(floatingIps.floatingIp(), floatingIps.id())) {
            log.debug("The floaing Ip {} that the floating Ip {} create for is used",
                      floatingIps.floatingIp().toString(), floatingIps.id()
                              .toString());
            throw new IllegalArgumentException(
                                               "The floating IP address is used");
        }

        IpAddress fixedIp = floatingIps.fixedIp();
        if (fixedIp != null
                && fixedIpIsUsed(fixedIp, floatingIps.tenantId(),
                                 floatingIps.id())) {
            log.debug("The fixed Ip {} that the floating Ip {} create for is used",
                      floatingIps.fixedIp().toString(), floatingIps.id()
                              .toString());
            throw new IllegalArgumentException("The fixed IP address is used");
        }
    }

    private class InnerFloatingIpStoreListener
            implements
            EventuallyConsistentMapListener<FloatingIpId, FloatingIp> {

        @Override
        public void event(EventuallyConsistentMapEvent<FloatingIpId, FloatingIp> event) {
            checkNotNull(event, EVENT_NOT_NULL);
            FloatingIp floatingIp = event.value();
            if (EventuallyConsistentMapEvent.Type.PUT == event.type()) {
                notifyListeners(new FloatingIpEvent(
                                                    FloatingIpEvent.Type.FLOATINGIP_PUT,
                                                    floatingIp));
                if (floatingIp.portId() != null) {
                    notifyListeners(new FloatingIpEvent(
                                                        FloatingIpEvent.Type.FLOATINGIP_BIND,
                                                        floatingIp));
                } else {
                    FloatingIp oldFloatingIp = floatingIpBindStore.get(floatingIp.id());
                    if (oldFloatingIp != null) {
                        notifyListeners(new FloatingIpEvent(
                                                            FloatingIpEvent.Type.FLOATINGIP_UNBIND,
                                                            oldFloatingIp));
                    }
                }
            }
            if (EventuallyConsistentMapEvent.Type.REMOVE == event.type()) {
                notifyListeners(new FloatingIpEvent(
                                                    FloatingIpEvent.Type.FLOATINGIP_DELETE,
                                                    floatingIp));
                if (floatingIp.portId() != null) {
                    notifyListeners(new FloatingIpEvent(
                                                        FloatingIpEvent.Type.FLOATINGIP_UNBIND,
                                                        floatingIp));
                }
            }
        }
    }

    /**
     * Notifies specify event to all listeners.
     *
     * @param event Floating IP event
     */
    private void notifyListeners(FloatingIpEvent event) {
        checkNotNull(event, EVENT_NOT_NULL);
        listeners.forEach(listener -> listener.event(event));
    }
}
