/*
 * Copyright 2015-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.vpls;

import com.google.common.collect.ImmutableSet;
import org.onosproject.net.EncapsulationType;
import org.onosproject.net.Host;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.net.intf.Interface;
import org.onosproject.net.intf.InterfaceService;
import org.onosproject.store.StoreDelegate;
import org.onosproject.vpls.api.Vpls;
import org.onosproject.vpls.api.VplsData;
import org.onosproject.vpls.api.VplsOperation;
import org.onosproject.vpls.api.VplsOperationService;
import org.onosproject.vpls.api.VplsStore;
import org.onosproject.vpls.store.VplsStoreEvent;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;

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

import static java.util.Objects.requireNonNull;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Application to create L2 broadcast overlay networks using VLANs.
 */
@Component(immediate = true, service = Vpls.class)
public class VplsManager implements Vpls {
    public static final String VPLS_APP = "org.onosproject.vpls";
    private static final String UNSUPPORTED_STORE_EVENT_TYPE =
            "Unsupported store event type {}.";
    private final Logger log = getLogger(getClass());

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected InterfaceService interfaceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected VplsStore vplsStore;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected VplsOperationService operationService;

    private StoreDelegate<VplsStoreEvent> vplsStoreDelegate;
    private HostListener vplsHostListener;

    @Activate
    public void activate() {
        vplsStoreDelegate = new VplsStoreDelegate();
        vplsHostListener = new VplsHostListener();

        vplsStore.setDelegate(vplsStoreDelegate);
        hostService.addListener(vplsHostListener);
    }

    @Deactivate
    public void deactivate() {
        vplsStore.unsetDelegate(vplsStoreDelegate);
        hostService.removeListener(vplsHostListener);
    }

    @Override
    public VplsData createVpls(String vplsName, EncapsulationType encapsulationType) {
        requireNonNull(vplsName);
        requireNonNull(encapsulationType);

        if (vplsStore.getVpls(vplsName) != null) {
            return null;
        }

        VplsData vplsData = VplsData.of(vplsName, encapsulationType);
        vplsStore.addVpls(vplsData);

        return vplsData;
    }

    @Override
    public VplsData removeVpls(VplsData vplsData) {
        requireNonNull(vplsData);
        VplsData newData = VplsData.of(vplsData);
        newData.state(VplsData.VplsState.REMOVING);
        vplsStore.removeVpls(vplsData);
        return vplsData;
    }

    @Override
    public void addInterfaces(VplsData vplsData, Collection<Interface> interfaces) {
        requireNonNull(vplsData);
        requireNonNull(interfaces);
        VplsData newData = VplsData.of(vplsData);
        newData.addInterfaces(interfaces);
        updateVplsStatus(newData, VplsData.VplsState.UPDATING);
    }

    @Override
    public void addInterface(VplsData vplsData, Interface iface) {
        requireNonNull(vplsData);
        requireNonNull(iface);
        VplsData newData = VplsData.of(vplsData);
        newData.addInterface(iface);
        updateVplsStatus(newData, VplsData.VplsState.UPDATING);
    }

    @Override
    public void setEncapsulationType(VplsData vplsData, EncapsulationType encapsulationType) {
        requireNonNull(vplsData);
        requireNonNull(encapsulationType);
        VplsData newData = VplsData.of(vplsData);
        if (newData.encapsulationType().equals(encapsulationType)) {
            // Encap type not changed.
            return;
        }
        newData.encapsulationType(encapsulationType);
        updateVplsStatus(newData, VplsData.VplsState.UPDATING);
    }

    @Override
    public VplsData getVpls(String vplsName) {
        requireNonNull(vplsName);
        return vplsStore.getVpls(vplsName);
    }

    @Override
    public Collection<Interface> removeInterfaces(VplsData vplsData, Collection<Interface> interfaces) {
        requireNonNull(vplsData);
        requireNonNull(interfaces);
        VplsData newData = VplsData.of(vplsData);
        newData.removeInterfaces(interfaces);
        updateVplsStatus(newData, VplsData.VplsState.UPDATING);
        return interfaces;
    }

    @Override
    public Interface removeInterface(VplsData vplsData, Interface iface) {
        requireNonNull(vplsData);
        requireNonNull(iface);
        VplsData newData = VplsData.of(vplsData);
        newData.removeInterface(iface);
        updateVplsStatus(newData, VplsData.VplsState.UPDATING);
        return iface;
    }

    @Override
    public void removeAllVpls() {
        Set<VplsData> allVplses = ImmutableSet.copyOf(vplsStore.getAllVpls());
        allVplses.forEach(this::removeVpls);
    }

    @Override
    public Collection<VplsData> getAllVpls() {
        return ImmutableSet.copyOf(vplsStore.getAllVpls());
    }

    /**
     * Updates VPLS status to the store.
     *
     * @param vplsData the VPLS
     * @param vplsState the new state to the VPLS
     */
    private void updateVplsStatus(VplsData vplsData, VplsData.VplsState vplsState) {
        vplsData.state(vplsState);
        vplsStore.updateVpls(vplsData);
    }

    /**
     * A listener for host events.
     * Updates a VPLS if host added or removed.
     */
    class VplsHostListener implements HostListener {
        @Override
        public void event(HostEvent event) {
            Host host = event.subject();
            Interface iface = getHostInterface(host);
            if (iface == null) {
                return;
            }
            VplsData vplsData = vplsStore.getAllVpls().stream()
                    .filter(v -> v.interfaces().contains(iface))
                    .findFirst()
                    .orElse(null);
            if (vplsData == null) {
                // the host does not related to any vpls
                return;
            }
            updateVplsStatus(vplsData, VplsData.VplsState.UPDATING);
        }

        /**
         * Gets the network interface of the host.
         *
         * @param host the host
         * @return the network interface of the host; null if no network
         * interface found
         */
        private Interface getHostInterface(Host host) {
            Set<Interface> interfaces = interfaceService.getInterfaces();
            return interfaces.stream()
                    .filter(iface -> iface.connectPoint().equals(host.location()) &&
                            iface.vlan().equals(host.vlan()))
                    .findFirst()
                    .orElse(null);
        }
    }

    /**
     * Store delegate for VPLS store.
     * Handles VPLS store event and generate VPLS operation according to event
     * type.
     */
    class VplsStoreDelegate implements StoreDelegate<VplsStoreEvent> {

        @Override
        public void notify(VplsStoreEvent event) {
            VplsOperation vplsOperation;
            VplsOperation.Operation op;
            VplsData vplsData = event.subject();
            switch (event.type()) {
                case ADD:
                    op = VplsOperation.Operation.ADD;
                    break;
                case REMOVE:
                    op = VplsOperation.Operation.REMOVE;
                    break;
                case UPDATE:
                    if (vplsData.state() == VplsData.VplsState.FAILED ||
                            vplsData.state() == VplsData.VplsState.ADDED ||
                            vplsData.state() == VplsData.VplsState.REMOVED) {
                        // Update the state only. Nothing to do if it is updated
                        // to ADDED, REMOVED or FAILED
                        op = null;
                    } else {
                        op = VplsOperation.Operation.UPDATE;
                    }
                    break;
                default:
                    log.warn(UNSUPPORTED_STORE_EVENT_TYPE, event.type());
                    return;
            }
            if (op != null) {
                vplsOperation = VplsOperation.of(vplsData, op);
                operationService.submit(vplsOperation);
            }
        }
    }
}
