/*
 * 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 freemarker.ext.beans;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import freemarker.ext.beans.MemberSelectorListMemberAccessPolicy.MemberSelector;
import freemarker.template.Version;
import freemarker.template._TemplateAPI;

/**
 * Member access policy to implement the default behavior that's mostly compatible with pre-2.3.30 versions, but is
 * somewhat safer; it still can't provide safety in practice, if you allow untrusted users to edit templates! Use
 * {@link WhitelistMemberAccessPolicy} if you need stricter control.
 *
 * @since 2.3.30
 */
public final class DefaultMemberAccessPolicy implements MemberAccessPolicy {

    private static final DefaultMemberAccessPolicy INSTANCE = new DefaultMemberAccessPolicy();

    private final Set<Class<?>> whitelistRuleFinalClasses;
    private final Set<Class<?>> whitelistRuleNonFinalClasses;
    private final WhitelistMemberAccessPolicy whitelistMemberAccessPolicy;
    private final BlacklistMemberAccessPolicy blacklistMemberAccessPolicy;
    private final boolean toStringAlwaysExposed;

    /**
     * Returns the singleton that's compatible with the given incompatible improvements version.
     */
    public static DefaultMemberAccessPolicy getInstance(Version incompatibleImprovements) {
        _TemplateAPI.checkVersionNotNullAndSupported(incompatibleImprovements);
        // All breakpoints here must occur in ClassIntrospectorBuilder.normalizeIncompatibleImprovementsVersion!
        // Though currently we don't have any.
        return INSTANCE;
    }

    private DefaultMemberAccessPolicy() {
        try {
            ClassLoader classLoader = DefaultMemberAccessPolicy.class.getClassLoader();

            whitelistRuleFinalClasses = new HashSet<>();
            whitelistRuleNonFinalClasses = new HashSet<>();
            Set<Class<?>> typesWithBlacklistUnlistedRule = new HashSet<>();
            List<MemberSelector> whitelistMemberSelectors = new ArrayList<>();
            for (String line : loadMemberSelectorFileLines()) {
                line = line.trim();
                if (!MemberSelector.isIgnoredLine(line)) {
                    if (line.startsWith("@")) {
                        String[] lineParts = line.split("\\s+");
                        if (lineParts.length != 2) {
                            throw new IllegalStateException("Malformed @ line: " + line);
                        }
                        String typeName = lineParts[1];
                        Class<?> upperBoundType;
                        try {
                            upperBoundType = classLoader.loadClass(typeName);
                        } catch (ClassNotFoundException e) {
                            upperBoundType = null;
                        }
                        String rule = lineParts[0].substring(1);
                        if (rule.equals("whitelistPolicyIfAssignable")) {
                            if (upperBoundType != null) {
                                Set<Class<?>> targetSet =
                                        (upperBoundType.getModifiers() & Modifier.FINAL) != 0
                                                ? whitelistRuleFinalClasses
                                                : whitelistRuleNonFinalClasses;
                                targetSet.add(upperBoundType);
                            }
                        } else if (rule.equals("blacklistUnlistedMembers")) {
                            if (upperBoundType != null) {
                                typesWithBlacklistUnlistedRule.add(upperBoundType);
                            }
                        } else {
                            throw new IllegalStateException("Unhandled rule: " + rule);
                        }
                    } else {
                        MemberSelector memberSelector;
                        try {
                            memberSelector = MemberSelector.parse(line, classLoader);
                        } catch (ClassNotFoundException | NoSuchMethodException | NoSuchFieldException e) {
                            // Can happen if we run on an older Java than the list was made for
                            memberSelector = null;
                        }
                        if (memberSelector != null) {
                            Class<?> upperBoundType = memberSelector.getUpperBoundType();
                            if (upperBoundType != null) {
                                if (!whitelistRuleFinalClasses.contains(upperBoundType)
                                        && !whitelistRuleNonFinalClasses.contains(upperBoundType)
                                        && !typesWithBlacklistUnlistedRule.contains(upperBoundType)) {
                                    throw new IllegalStateException("Type without rule: " + upperBoundType.getName());
                                }
                                // We always do the same, as "blacklistUnlistedMembers" is also defined via a whitelist:
                                whitelistMemberSelectors.add(memberSelector);
                            }
                        }
                    }
                }
            }

            whitelistMemberAccessPolicy = new WhitelistMemberAccessPolicy(whitelistMemberSelectors);

            // Generate blacklists based on the whitelist and the members of "blacklistUnlistedMembers" types:
            List<MemberSelector> blacklistMemberSelectors = new ArrayList<>();
            for (Class<?> blacklistUnlistedRuleType : typesWithBlacklistUnlistedRule) {
                ClassMemberAccessPolicy classPolicy = whitelistMemberAccessPolicy.forClass(blacklistUnlistedRuleType);
                for (Method method : blacklistUnlistedRuleType.getMethods()) {
                    if (!classPolicy.isMethodExposed(method)) {
                        blacklistMemberSelectors.add(new MemberSelector(blacklistUnlistedRuleType, method));
                    }
                }
                for (Constructor<?> constructor : blacklistUnlistedRuleType.getConstructors()) {
                    if (!classPolicy.isConstructorExposed(constructor)) {
                        blacklistMemberSelectors.add(new MemberSelector(blacklistUnlistedRuleType, constructor));
                    }
                }
                for (Field field : blacklistUnlistedRuleType.getFields()) {
                    if (!classPolicy.isFieldExposed(field)) {
                        blacklistMemberSelectors.add(new MemberSelector(blacklistUnlistedRuleType, field));
                    }
                }
            }
            blacklistMemberAccessPolicy = new BlacklistMemberAccessPolicy(blacklistMemberSelectors);

            toStringAlwaysExposed =
                    whitelistMemberAccessPolicy.isToStringAlwaysExposed()
                    && blacklistMemberAccessPolicy.isToStringAlwaysExposed();
        } catch (Exception e) {
            throw new IllegalStateException("Couldn't init " + this.getClass().getName() + " instance", e);
        }
    }

    private static List<String> loadMemberSelectorFileLines() throws IOException {
        List<String> whitelist = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(
                        DefaultMemberAccessPolicy.class.getResourceAsStream("DefaultMemberAccessPolicy-rules"),
                        "UTF-8"))) {
            String line;
            while ((line = reader.readLine()) != null) {
                whitelist.add(line);
            }
        }

        return whitelist;
    }

    @Override
    public ClassMemberAccessPolicy forClass(Class<?> contextClass) {
        if (isTypeWithWhitelistRule(contextClass)) {
            return whitelistMemberAccessPolicy.forClass(contextClass);
        } else {
            return blacklistMemberAccessPolicy.forClass(contextClass);
        }
    }

    @Override
    public boolean isToStringAlwaysExposed() {
        return toStringAlwaysExposed;
    }

    private boolean isTypeWithWhitelistRule(Class<?> contextClass) {
        if (whitelistRuleFinalClasses.contains(contextClass)) {
            return true;
        }
        for (Class<?> nonFinalClass : whitelistRuleNonFinalClasses) {
            if (nonFinalClass.isAssignableFrom(contextClass)) {
                return true;
            }
        }
        return false;
    }

}
