/*
 * Copyright 2017 HugeGraph Authors
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with this
 * work for additional information regarding copyright ownership. The ASF
 * licenses this file to You 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.apache.hugegraph.config;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.hugegraph.util.E;
import org.apache.hugegraph.util.Log;
import org.slf4j.Logger;

public final class OptionSpace {

    private static final Logger LOG = Log.logger(OptionSpace.class);

    private static final Map<String, Class<? extends OptionHolder>> HOLDERS;
    private static final Map<String, TypedOption<?, ?>> OPTIONS;
    private static final String INSTANCE_METHOD = "instance";

    static {
        HOLDERS = new ConcurrentHashMap<>();
        OPTIONS = new ConcurrentHashMap<>();
    }

    public static void register(String module, String holder) {
        ClassLoader classLoader = OptionSpace.class.getClassLoader();
        Class<?> clazz;
        try {
            clazz = classLoader.loadClass(holder);
        } catch (ClassNotFoundException e) {
            throw new ConfigException(
                      "Failed to load class of option holder '%s'", e, holder);
        }

        // Check subclass
        if (!OptionHolder.class.isAssignableFrom(clazz)) {
            throw new ConfigException(
                      "Class '%s' is not a subclass of OptionHolder", holder);
        }

        OptionHolder instance = null;
        Exception exception = null;
        try {
            Method method = clazz.getMethod(INSTANCE_METHOD);
            if (!Modifier.isStatic(method.getModifiers())) {
                throw new NoSuchMethodException(INSTANCE_METHOD);
            }
            instance = (OptionHolder) method.invoke(null);
            if (instance == null) {
                exception = new ConfigException(
                                "Returned null from %s() method",
                                INSTANCE_METHOD);
            }
        } catch (NoSuchMethodException e) {
            LOG.warn("Class {} does not has static method {}.",
                     holder, INSTANCE_METHOD);
            exception = e;
        } catch (InvocationTargetException e) {
            LOG.warn("Can't call static method {} from class {}.",
                     INSTANCE_METHOD, holder);
            exception = e;
        } catch (IllegalAccessException e) {
            LOG.warn("Illegal access while calling method {} from class {}.",
                     INSTANCE_METHOD, holder);
            exception = e;
        }

        if (exception != null) {
            throw new ConfigException("Failed to instantiate option holder: %s",
                                      exception, holder);
        }

        register(module, instance);
    }

    public static void register(String module, OptionHolder holder) {
        // Check exists
        if (HOLDERS.containsKey(module)) {
            LOG.warn("Already registered option holder: {} ({})",
                     module, HOLDERS.get(module));
        }
        E.checkArgumentNotNull(holder, "OptionHolder can't be null");
        HOLDERS.put(module, holder.getClass());
        OPTIONS.putAll(holder.options());
        LOG.debug("Registered options for OptionHolder: {}",
                  holder.getClass().getSimpleName());
    }

    public static Set<String> keys() {
        return Collections.unmodifiableSet(OPTIONS.keySet());
    }

    public static boolean containKey(String key) {
        return OPTIONS.containsKey(key);
    }

    public static TypedOption<?, ?> get(String key) {
        return OPTIONS.get(key);
    }
}
