package com.qmth.boot.core.security.service.impl;

import com.qmth.boot.core.security.service.AuthorizationService;
import com.qmth.boot.core.security.service.AuthorizationServiceRegistration;
import com.qmth.boot.tools.signature.SignatureType;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.Map;

public class AuthorizationServiceContainer implements AuthorizationServiceRegistration {

    private static final String NULL_SIGNATURE_TYPE_PLACEHOLDER = "#";

    private Map<String, AuthorizationService> defaultMap;

    private Map<String, Map<String, AuthorizationService>> pathMap;

    public AuthorizationServiceContainer() {
        this.defaultMap = new HashMap<>();
        this.pathMap = new HashMap<>();
    }

    @Override
    public AuthorizationServiceRegistration setPrefix(@NotBlank String prefix, @NotNull AuthorizationService service) {
        pathMap.computeIfAbsent(prefix, key -> new HashMap<>()).put(NULL_SIGNATURE_TYPE_PLACEHOLDER, service);
        return this;
    }

    @Override
    public AuthorizationServiceRegistration setPrefix(@NotBlank String prefix, @NotNull SignatureType type,
            @NotNull AuthorizationService service) {
        pathMap.computeIfAbsent(prefix, key -> new HashMap<>()).put(type.getName(), service);
        return this;
    }

    @Override
    public AuthorizationServiceRegistration setDefault(@NotNull SignatureType type,
            @NotNull AuthorizationService service) {
        defaultMap.put(type.getName(), service);
        return this;
    }

    @Override
    public AuthorizationServiceRegistration setDefault(@NotNull AuthorizationService service) {
        defaultMap.put(NULL_SIGNATURE_TYPE_PLACEHOLDER, service);
        return this;
    }

    public AuthorizationService find(String path, SignatureType type) {
        AuthorizationService service = null;
        // 按路径前缀规则查找
        int length = 0;
        for (Map.Entry<String, Map<String, AuthorizationService>> entry : pathMap.entrySet()) {
            if (path.startsWith(entry.getKey()) && entry.getKey().length() > length) {
                AuthorizationService item = find(entry.getValue(), type);
                if (item != null) {
                    service = item;
                    length = entry.getKey().length();
                }
            }
        }
        // 最后查找默认服务
        if (service == null) {
            service = find(defaultMap, type);
        }
        return service;
    }

    private AuthorizationService find(Map<String, AuthorizationService> map, SignatureType type) {
        AuthorizationService service = null;
        if (map != null) {
            service = map.get(type.getName());
            if (service == null) {
                service = map.get(NULL_SIGNATURE_TYPE_PLACEHOLDER);
            }
        }
        return service;
    }
}
