/*
 * Copyright 2016-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.config.impl;

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.config.RpcExecutor;
import org.onosproject.config.RpcMessageId;
import org.onosproject.d.config.DeviceResourceIds;
import org.onosproject.d.config.ResourceIds;
import org.onosproject.event.AbstractListenerManager;
import org.onosproject.config.DynamicConfigEvent;
import org.onosproject.config.DynamicConfigListener;
import org.onosproject.config.DynamicConfigService;
import org.onosproject.config.DynamicConfigStore;
import org.onosproject.config.DynamicConfigStoreDelegate;
import org.onosproject.config.FailedException;
import org.onosproject.config.Filter;
import org.onosproject.yang.model.RpcInput;
import org.onosproject.yang.model.RpcOutput;
import org.onosproject.yang.model.DataNode;
import org.onosproject.yang.model.DataNode.Type;
import org.onosproject.yang.model.InnerNode;
import org.onosproject.yang.model.ResourceId;
import org.onosproject.yang.model.RpcContext;
import org.onosproject.yang.model.RpcRegistry;
import org.onosproject.yang.model.RpcService;
import org.onosproject.yang.model.SchemaContextProvider;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;

import static org.onosproject.d.config.DeviceResourceIds.DCS_NAMESPACE;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Implementation of the Dynamic Config Service.
 *
 */
@Component(immediate = true)
@Service
public class DynamicConfigManager
        extends AbstractListenerManager<DynamicConfigEvent, DynamicConfigListener>
        implements DynamicConfigService, RpcRegistry {

    private final Logger log = getLogger(getClass());
    private final DynamicConfigStoreDelegate storeDelegate = new InternalStoreDelegate();

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DynamicConfigStore store;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected SchemaContextProvider contextProvider;

    // FIXME is it OK this is not using the Store?
    private ConcurrentHashMap<String, RpcService> handlerRegistry = new ConcurrentHashMap<>();

    @Activate
    public void activate() {
        initStore();
        store.setDelegate(storeDelegate);
        eventDispatcher.addSink(DynamicConfigEvent.class, listenerRegistry);
        log.info("Started");
    }

    /**
     * Ensure built-in tree nodes exists.
     */
    private void initStore() {
        store.nodeExist(ResourceIds.ROOT_ID)
            .thenAccept(exists -> {
                if (!exists) {
                    log.info("Root node does not exist!, creating...");
                    store.addNode(null,
                                  InnerNode.builder(DeviceResourceIds.ROOT_NAME, DCS_NAMESPACE)
                                  .type(Type.SINGLE_INSTANCE_NODE).build());
                }
            }).join();

        store.nodeExist(DeviceResourceIds.DEVICES_ID)
            .thenAccept(exists -> {
                if (!exists) {
                    log.info("devices node does not exist!, creating...");
                    store.addNode(ResourceIds.ROOT_ID,
                                  InnerNode.builder(DeviceResourceIds.DEVICES_NAME, DCS_NAMESPACE)
                                  .type(Type.SINGLE_INSTANCE_NODE).build());
                }
            }).join();
    }

    @Deactivate
    public void deactivate() {
        store.unsetDelegate(storeDelegate);
        eventDispatcher.removeSink(DynamicConfigEvent.class);
        handlerRegistry.clear();
        log.info("Stopped");
    }

    @Override
    public void createNode(ResourceId path, DataNode node) {
        store.addNode(path, node).join();
    }

    @Override
    public DataNode readNode(ResourceId path, Filter filter) {
        return store.readNode(path, filter).join();
    }

    @Override
    public void updateNode(ResourceId path, DataNode node) {
        store.updateNode(path, node).join();
    }

    @Override
    public void deleteNode(ResourceId path) {
        store.deleteNodeRecursive(path).join();
    }

    @Override
    public void replaceNode(ResourceId path, DataNode node) {
        throw new FailedException("Not yet implemented");
    }

    @Override
    public Boolean nodeExist(ResourceId path) {
        return store.nodeExist(path).join();
    }

    @Override
    public Set<RpcService> getRpcServices() {
        Set<RpcService> res = new HashSet();
        for (Map.Entry<String, RpcService> e : handlerRegistry.entrySet()) {
            res.add(e.getValue());
        }
        return res;
    }

    @Override
    public RpcService getRpcService(Class<? extends RpcService> intfc) {
        return handlerRegistry.get(intfc.getName());
    }

    @Override
    public void registerRpcService(RpcService handler) {
        for (Class<?> intfc : handler.getClass().getInterfaces()) {
            if (RpcService.class.isAssignableFrom(intfc)) {
                handlerRegistry.put(intfc.getName(), handler);
            }
        }
    }

    @Override
    public void unregisterRpcService(RpcService handler) {
        for (Class<?> intfc : handler.getClass().getInterfaces()) {
            if (RpcService.class.isAssignableFrom(intfc)) {
                String key = intfc.getName();
                if (handlerRegistry.get(key) == null) {
                    throw new FailedException("No registered handler found, cannot unregister");
                }
                handlerRegistry.remove(key);
            }
        }
    }

    private int getSvcId(RpcService handler, String srvc) {
        Class<?>[] intfcs = handler.getClass().getInterfaces();
        for (int i = 0; i < intfcs.length; i++) {
            if (intfcs[i].getName().compareTo(srvc) == 0) {
                return i;
            }
        }
        throw new FailedException("No handler found, cannot invoke");
    }

    @Override
    public CompletableFuture<RpcOutput> invokeRpc(ResourceId id, RpcInput input) {
        RpcContext context = contextProvider.getRpcContext(id);
        String srvcIntf = context.serviceIntf().getName();
        RpcService handler = handlerRegistry.get(srvcIntf);
        if (handler == null) {
            throw new FailedException("No registered handler found, cannot invoke");
        }
        return CompletableFuture.supplyAsync(
                new RpcExecutor(handler, getSvcId(handler, srvcIntf),
                                context.rpcName(), RpcMessageId.generate(), input));
    }

    /**
     * Auxiliary store delegate to receive notification about changes in the store.
     */
    private class InternalStoreDelegate implements DynamicConfigStoreDelegate {
        @Override
        public void notify(DynamicConfigEvent event) {
            post(event);
        }
    }
}