/*
 * Copyright 2017-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.openstacknetworking.impl;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
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.CoreService;
import org.onosproject.event.ListenerRegistry;
import org.onosproject.openstacknetworking.api.Constants;
import org.onosproject.openstacknetworking.api.OpenstackRouterAdminService;
import org.onosproject.openstacknetworking.api.OpenstackRouterEvent;
import org.onosproject.openstacknetworking.api.OpenstackRouterListener;
import org.onosproject.openstacknetworking.api.OpenstackRouterService;
import org.onosproject.openstacknetworking.api.OpenstackRouterStore;
import org.onosproject.openstacknetworking.api.OpenstackRouterStoreDelegate;
import org.openstack4j.model.network.NetFloatingIP;
import org.openstack4j.model.network.Router;
import org.openstack4j.model.network.RouterInterface;
import org.slf4j.Logger;

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

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

/**
 * Provides implementation of administering and interfacing OpenStack router and
 * floating IP address.
 */
@Service
@Component(immediate = true)
public class OpenstackRouterManager
        extends ListenerRegistry<OpenstackRouterEvent, OpenstackRouterListener>
        implements OpenstackRouterAdminService, OpenstackRouterService {

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

    private static final String MSG_ROUTER = "OpenStack router %s %s";
    private static final String MSG_ROUTER_IFACE = "OpenStack router interface %s %s";
    private static final String MSG_FLOATING_IP = "OpenStack floating IP %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_ROUTER = "OpenStack router cannot be null";
    private static final String ERR_NULL_ROUTER_ID = "OpenStack router ID cannot be null";
    private static final String ERR_NULL_ROUTER_NAME = "OpenStack router name cannot be null";
    private static final String ERR_NULL_IFACE = "OpenStack router interface cannot be null";
    private static final String ERR_NULL_IFACE_ROUTER_ID = "OpenStack router interface router ID cannot be null";
    private static final String ERR_NULL_IFACE_PORT_ID = "OpenStack router interface port ID cannot be null";
    private static final String ERR_NULL_FLOATING = "OpenStack floating IP cannot be null";
    private static final String ERR_NULL_FLOATING_ID = "OpenStack floating IP cannot be null";

    private static final String ERR_IN_USE = " still in use";

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected OpenstackRouterStore osRouterStore;

    private final OpenstackRouterStoreDelegate delegate = new InternalRouterStoreDelegate();

    @Activate
    protected void activate() {
        coreService.registerApplication(Constants.OPENSTACK_NETWORKING_APP_ID);
        osRouterStore.setDelegate(delegate);
        log.info("Started");
    }

    @Deactivate
    protected void deactivate() {
        osRouterStore.unsetDelegate(delegate);
        log.info("Stopped");
    }

    @Override
    public void createRouter(Router osRouter) {
        checkNotNull(osRouter, ERR_NULL_ROUTER);
        checkArgument(!Strings.isNullOrEmpty(osRouter.getId()), ERR_NULL_ROUTER_ID);
        checkArgument(!Strings.isNullOrEmpty(osRouter.getName()), ERR_NULL_ROUTER_NAME);

        osRouterStore.createRouter(osRouter);
        log.info(String.format(MSG_ROUTER, osRouter.getName(), MSG_CREATED));
    }

    @Override
    public void updateRouter(Router osRouter) {
        checkNotNull(osRouter, ERR_NULL_ROUTER);
        checkArgument(!Strings.isNullOrEmpty(osRouter.getId()), ERR_NULL_ROUTER_ID);
        checkArgument(!Strings.isNullOrEmpty(osRouter.getName()), ERR_NULL_ROUTER_NAME);

        osRouterStore.updateRouter(osRouter);
        log.info(String.format(MSG_ROUTER, osRouter.getId(), MSG_UPDATED));
    }

    @Override
    public void removeRouter(String routerId) {
        checkArgument(!Strings.isNullOrEmpty(routerId), ERR_NULL_ROUTER_ID);
        synchronized (this) {
            if (isRouterInUse(routerId)) {
                final String error = String.format(MSG_ROUTER, routerId, ERR_IN_USE);
                throw new IllegalStateException(error);
            }
            Router osRouter = osRouterStore.removeRouter(routerId);
            if (osRouter != null) {
                log.info(String.format(MSG_ROUTER, osRouter.getName(), MSG_REMOVED));
            }
        }
    }

    @Override
    public void addRouterInterface(RouterInterface osIface) {
        checkNotNull(osIface, ERR_NULL_IFACE);
        checkArgument(!Strings.isNullOrEmpty(osIface.getId()), ERR_NULL_IFACE_ROUTER_ID);
        checkArgument(!Strings.isNullOrEmpty(osIface.getPortId()), ERR_NULL_IFACE_PORT_ID);

        osRouterStore.addRouterInterface(osIface);
        log.info(String.format(MSG_ROUTER_IFACE, osIface.getPortId(), MSG_CREATED));
    }

    @Override
    public void updateRouterInterface(RouterInterface osIface) {
        checkNotNull(osIface, ERR_NULL_IFACE);
        checkArgument(!Strings.isNullOrEmpty(osIface.getId()), ERR_NULL_IFACE_ROUTER_ID);
        checkArgument(!Strings.isNullOrEmpty(osIface.getPortId()), ERR_NULL_IFACE_PORT_ID);

        osRouterStore.updateRouterInterface(osIface);
        log.info(String.format(MSG_ROUTER_IFACE, osIface.getPortId(), MSG_UPDATED));
    }

    @Override
    public void removeRouterInterface(String osIfaceId) {
        checkArgument(!Strings.isNullOrEmpty(osIfaceId), ERR_NULL_IFACE_PORT_ID);
        synchronized (this) {
            if (isRouterIfaceInUse(osIfaceId)) {
                final String error = String.format(MSG_ROUTER, osIfaceId, ERR_IN_USE);
                throw new IllegalStateException(error);
            }
            RouterInterface osIface = osRouterStore.removeRouterInterface(osIfaceId);
            if (osIface != null) {
                log.info(String.format(MSG_ROUTER_IFACE, osIface.getPortId(), MSG_REMOVED));
            }
        }
    }

    @Override
    public void createFloatingIp(NetFloatingIP osFloatingIp) {
        checkNotNull(osFloatingIp, ERR_NULL_FLOATING);
        checkArgument(!Strings.isNullOrEmpty(osFloatingIp.getId()), ERR_NULL_FLOATING_ID);

        osRouterStore.createFloatingIp(osFloatingIp);
        log.info(String.format(MSG_FLOATING_IP, osFloatingIp.getId(), MSG_CREATED));
    }

    @Override
    public void updateFloatingIp(NetFloatingIP osFloatingIp) {
        checkNotNull(osFloatingIp, ERR_NULL_FLOATING);
        checkArgument(!Strings.isNullOrEmpty(osFloatingIp.getId()), ERR_NULL_FLOATING_ID);

        osRouterStore.updateFloatingIp(osFloatingIp);
        log.info(String.format(MSG_FLOATING_IP, osFloatingIp.getId(), MSG_UPDATED));
    }

    @Override
    public void removeFloatingIp(String floatingIpId) {
        checkArgument(!Strings.isNullOrEmpty(floatingIpId), ERR_NULL_FLOATING_ID);
        synchronized (this) {
            if (isFloatingIpInUse(floatingIpId)) {
                final String error = String.format(MSG_FLOATING_IP, floatingIpId, ERR_IN_USE);
                throw new IllegalStateException(error);
            }
            NetFloatingIP osFloatingIp = osRouterStore.removeFloatingIp(floatingIpId);
            if (osFloatingIp != null) {
                log.info(String.format(MSG_FLOATING_IP, osFloatingIp.getId(), MSG_REMOVED));
            }
        }
    }

    @Override
    public void clear() {
        osRouterStore.clear();
    }

    @Override
    public Router router(String routerId) {
        checkArgument(!Strings.isNullOrEmpty(routerId), ERR_NULL_ROUTER_ID);
        return osRouterStore.router(routerId);
    }

    @Override
    public Set<Router> routers() {
        return osRouterStore.routers();
    }

    @Override
    public RouterInterface routerInterface(String osIfaceId) {
        checkArgument(!Strings.isNullOrEmpty(osIfaceId), ERR_NULL_IFACE_PORT_ID);
        return osRouterStore.routerInterface(osIfaceId);
    }

    @Override
    public Set<RouterInterface> routerInterfaces() {
        return osRouterStore.routerInterfaces();
    }

    @Override
    public Set<RouterInterface> routerInterfaces(String routerId) {
        Set<RouterInterface> osIfaces = osRouterStore.routerInterfaces().stream()
                .filter(iface -> Objects.equals(iface.getId(), routerId))
                .collect(Collectors.toSet());
        return ImmutableSet.copyOf(osIfaces);
    }

    @Override
    public NetFloatingIP floatingIp(String floatingIpId) {
        checkArgument(!Strings.isNullOrEmpty(floatingIpId), ERR_NULL_FLOATING_ID);
        return osRouterStore.floatingIp(floatingIpId);
    }

    @Override
    public Set<NetFloatingIP> floatingIps() {
        return osRouterStore.floatingIps();
    }

    @Override
    public Set<NetFloatingIP> floatingIps(String routerId) {
        Set<NetFloatingIP> osFloatingIps = osRouterStore.floatingIps().stream()
                .filter(fip -> Objects.equals(fip.getRouterId(), routerId))
                .collect(Collectors.toSet());
        return ImmutableSet.copyOf(osFloatingIps);
    }

    private boolean isRouterInUse(String routerId) {
        // TODO add checking
        return false;
    }

    private boolean isRouterIfaceInUse(String osIfaceId) {
        // TODO add checking
        return false;
    }

    private boolean isFloatingIpInUse(String floatingIpId) {
        // TODO add checking
        return false;
    }

    private class InternalRouterStoreDelegate implements OpenstackRouterStoreDelegate {

        @Override
        public void notify(OpenstackRouterEvent event) {
            if (event != null) {
                log.trace("send openstack routing event {}", event);
                process(event);
            }
        }
    }
}
