/*
 * 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.dubbo.rpc.model;

import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.config.ReferenceConfigBase;
import org.apache.dubbo.config.ServiceConfigBase;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * Service repository for module
 */
public class ModuleServiceRepository {

    private final ModuleModel moduleModel;

    /**
     * services
     */
    private final ConcurrentMap<String, List<ServiceDescriptor>> services = new ConcurrentHashMap<>();

    /**
     * consumers ( key - group/interface:version value - consumerModel list)
     */
    private final ConcurrentMap<String, List<ConsumerModel>> consumers = new ConcurrentHashMap<>();

    /**
     * providers
     */
    private final ConcurrentMap<String, ProviderModel> providers = new ConcurrentHashMap<>();
    private final FrameworkServiceRepository frameworkServiceRepository;

    public ModuleServiceRepository(ModuleModel moduleModel) {
        this.moduleModel = moduleModel;
        frameworkServiceRepository = ScopeModelUtil.getFrameworkModel(moduleModel).getServiceRepository();
    }

    public ModuleModel getModuleModel() {
        return moduleModel;
    }

    /**
     * @deprecated Replaced to {@link ModuleServiceRepository#registerConsumer(ConsumerModel)}
     */
    @Deprecated
    public void registerConsumer(String serviceKey,
                                 ServiceDescriptor serviceDescriptor,
                                 ReferenceConfigBase<?> rc,
                                 Object proxy,
                                 ServiceMetadata serviceMetadata) {
        ClassLoader classLoader = null;
        if (rc != null) {
            classLoader = rc.getInterfaceClassLoader();
        }
        ConsumerModel consumerModel = new ConsumerModel(serviceMetadata.getServiceKey(), proxy, serviceDescriptor,
            serviceMetadata, null, classLoader);
        this.registerConsumer(consumerModel);
    }

    public void registerConsumer(ConsumerModel consumerModel) {
        consumers.computeIfAbsent(consumerModel.getServiceKey(), (serviceKey) -> new CopyOnWriteArrayList<>()).add(consumerModel);
    }

    /**
     * @deprecated Replaced to {@link ModuleServiceRepository#registerProvider(ProviderModel)}
     */
    @Deprecated
    public void registerProvider(String serviceKey,
                                 Object serviceInstance,
                                 ServiceDescriptor serviceModel,
                                 ServiceConfigBase<?> serviceConfig,
                                 ServiceMetadata serviceMetadata) {
        ClassLoader classLoader = null;
        Class<?> cla = null;
        if (serviceConfig != null) {
            classLoader = serviceConfig.getInterfaceClassLoader();
            cla = serviceConfig.getInterfaceClass();
        }
        ProviderModel providerModel = new ProviderModel(serviceKey, serviceInstance, serviceModel,
            serviceMetadata, classLoader);
        this.registerProvider(providerModel);
    }

    public void registerProvider(ProviderModel providerModel) {
        providers.putIfAbsent(providerModel.getServiceKey(), providerModel);
        frameworkServiceRepository.registerProvider(providerModel);
    }

    public ServiceDescriptor registerService(ServiceDescriptor serviceDescriptor) {
        return registerService(serviceDescriptor.getServiceInterfaceClass(), serviceDescriptor);
    }

    public ServiceDescriptor registerService(Class<?> interfaceClazz) {
        ServiceDescriptor serviceDescriptor = new ReflectionServiceDescriptor(interfaceClazz);
        return registerService(interfaceClazz, serviceDescriptor);
    }

    public ServiceDescriptor registerService(Class<?> interfaceClazz, ServiceDescriptor serviceDescriptor) {
        List<ServiceDescriptor> serviceDescriptors = services.computeIfAbsent(interfaceClazz.getName(),
            k -> new CopyOnWriteArrayList<>());
        synchronized (serviceDescriptors) {
            Optional<ServiceDescriptor> previous = serviceDescriptors.stream()
                .filter(s -> s.getServiceInterfaceClass().equals(interfaceClazz)).findFirst();
            if (previous.isPresent()) {
                return previous.get();
            } else {
                serviceDescriptors.add(serviceDescriptor);
                return serviceDescriptor;
            }
        }
    }

    /**
     * See {@link #registerService(Class)}
     * <p>
     * we assume:
     * 1. services with different interfaces are not allowed to have the same path.
     * 2. services share the same interface but has different group/version can share the same path.
     * 3. path's default value is the name of the interface.
     *
     * @param path
     * @param interfaceClass
     * @return
     */
    public ServiceDescriptor registerService(String path, Class<?> interfaceClass) {
        ServiceDescriptor serviceDescriptor = registerService(interfaceClass);
        // if path is different with interface name, add extra path mapping
        if (!interfaceClass.getName().equals(path)) {
            List<ServiceDescriptor> serviceDescriptors = services.computeIfAbsent(path,
                _k -> new CopyOnWriteArrayList<>());
            synchronized (serviceDescriptors) {
                Optional<ServiceDescriptor> previous = serviceDescriptors.stream()
                    .filter(s -> s.getServiceInterfaceClass().equals(serviceDescriptor.getServiceInterfaceClass())).findFirst();
                if (previous.isPresent()) {
                    return previous.get();
                } else {
                    serviceDescriptors.add(serviceDescriptor);
                    return serviceDescriptor;
                }
            }
        }
        return serviceDescriptor;
    }

    @Deprecated
    public void reRegisterProvider(String newServiceKey, String serviceKey) {
        ProviderModel providerModel = this.providers.get(serviceKey);
        frameworkServiceRepository.unregisterProvider(providerModel);
        providerModel.setServiceKey(newServiceKey);
        this.providers.putIfAbsent(newServiceKey, providerModel);
        frameworkServiceRepository.registerProvider(providerModel);
        this.providers.remove(serviceKey);
    }

    @Deprecated
    public void reRegisterConsumer(String newServiceKey, String serviceKey) {
        List<ConsumerModel> consumerModel = this.consumers.get(serviceKey);
        consumerModel.forEach(c -> c.setServiceKey(newServiceKey));
        this.consumers.computeIfAbsent(newServiceKey, (k) -> new CopyOnWriteArrayList<>()).addAll(consumerModel);
        this.consumers.remove(serviceKey);
    }

    public void unregisterService(Class<?> interfaceClazz) {
        // TODO remove
        unregisterService(interfaceClazz.getName());
    }

    public void unregisterService(String path) {
        services.remove(path);
    }

    public void unregisterProvider(ProviderModel providerModel) {
        frameworkServiceRepository.unregisterProvider(providerModel);
        providers.remove(providerModel.getServiceKey());
    }

    public void unregisterConsumer(ConsumerModel consumerModel) {
        consumers.get(consumerModel.getServiceKey()).remove(consumerModel);
    }

    public List<ServiceDescriptor> getAllServices() {
        List<ServiceDescriptor> serviceDescriptors = services.values().stream().flatMap(Collection::stream).collect(Collectors.toList());
        return Collections.unmodifiableList(serviceDescriptors);
    }

    public ServiceDescriptor getService(String serviceName) {
        // TODO, may need to distinguish service by class loader.
        List<ServiceDescriptor> serviceDescriptors = services.get(serviceName);
        if (CollectionUtils.isEmpty(serviceDescriptors)) {
            return null;
        }
        return serviceDescriptors.get(0);
    }

    public ServiceDescriptor lookupService(String interfaceName) {
        if (interfaceName != null && services.containsKey(interfaceName)) {
            List<ServiceDescriptor> serviceDescriptors = services.get(interfaceName);
            return serviceDescriptors.size() > 0 ? serviceDescriptors.get(0) : null;
        } else {
            return null;
        }
    }

    public MethodDescriptor lookupMethod(String interfaceName, String methodName) {
        ServiceDescriptor serviceDescriptor = lookupService(interfaceName);
        if (serviceDescriptor == null) {
            return null;
        }

        List<MethodDescriptor> methods = serviceDescriptor.getMethods(methodName);
        if (CollectionUtils.isEmpty(methods)) {
            return null;
        }
        return methods.iterator().next();
    }

    public List<ProviderModel> getExportedServices() {
        return Collections.unmodifiableList(new ArrayList<>(providers.values()));
    }

    public ProviderModel lookupExportedService(String serviceKey) {
        return providers.get(serviceKey);
    }

    public List<ConsumerModel> getReferredServices() {
        List<ConsumerModel> consumerModels = consumers.values().stream().flatMap(Collection::stream).collect(Collectors.toList());
        return Collections.unmodifiableList(consumerModels);
    }

    /**
     * @deprecated Replaced to {@link ModuleServiceRepository#lookupReferredServices(String)}
     */
    @Deprecated
    public ConsumerModel lookupReferredService(String serviceKey) {
        if (consumers.containsKey(serviceKey)) {
            List<ConsumerModel> consumerModels = consumers.get(serviceKey);
            return consumerModels.size() > 0 ? consumerModels.get(0) : null;
        } else {
            return null;
        }
    }

    public List<ConsumerModel> lookupReferredServices(String serviceKey) {
        return consumers.get(serviceKey);
    }

    public void destroy() {
        for (ProviderModel providerModel : providers.values()) {
            frameworkServiceRepository.unregisterProvider(providerModel);
        }
        providers.clear();
        consumers.clear();
        services.clear();
    }
}
