/*
 * 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.maven.project.interpolation;

import javax.inject.Named;
import javax.inject.Singleton;

import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;

import org.apache.maven.model.Model;
import org.apache.maven.project.ProjectBuilderConfiguration;
import org.apache.maven.project.path.PathTranslator;
import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
import org.codehaus.plexus.interpolation.Interpolator;
import org.codehaus.plexus.interpolation.StringSearchInterpolator;
import org.codehaus.plexus.interpolation.ValueSource;
import org.codehaus.plexus.logging.Logger;

/**
 * StringSearchModelInterpolator
 */
@Deprecated
@Named
@Singleton
public class StringSearchModelInterpolator extends AbstractStringBasedModelInterpolator {

    private static final Map<Class<?>, Field[]> FIELDS_BY_CLASS = new WeakHashMap<>();
    private static final Map<Class<?>, Boolean> PRIMITIVE_BY_CLASS = new WeakHashMap<>();

    public StringSearchModelInterpolator() {}

    public StringSearchModelInterpolator(PathTranslator pathTranslator) {
        super(pathTranslator);
    }

    public Model interpolate(Model model, File projectDir, ProjectBuilderConfiguration config, boolean debugEnabled)
            throws ModelInterpolationException {
        interpolateObject(model, model, projectDir, config, debugEnabled);

        return model;
    }

    protected void interpolateObject(
            Object obj, Model model, File projectDir, ProjectBuilderConfiguration config, boolean debugEnabled)
            throws ModelInterpolationException {
        try {
            List<ValueSource> valueSources = createValueSources(model, projectDir, config);
            List<InterpolationPostProcessor> postProcessors = createPostProcessors(model, projectDir, config);

            InterpolateObjectAction action =
                    new InterpolateObjectAction(obj, valueSources, postProcessors, debugEnabled, this, getLogger());

            ModelInterpolationException error = AccessController.doPrivileged(action);

            if (error != null) {
                throw error;
            }
        } finally {
            getInterpolator().clearAnswers();
        }
    }

    protected Interpolator createInterpolator() {
        StringSearchInterpolator interpolator = new StringSearchInterpolator();
        interpolator.setCacheAnswers(true);

        return interpolator;
    }

    private static final class InterpolateObjectAction implements PrivilegedAction<ModelInterpolationException> {

        private final boolean debugEnabled;
        private final LinkedList<Object> interpolationTargets;
        private final StringSearchModelInterpolator modelInterpolator;
        private final Logger logger;
        private final List<ValueSource> valueSources;
        private final List<InterpolationPostProcessor> postProcessors;

        InterpolateObjectAction(
                Object target,
                List<ValueSource> valueSources,
                List<InterpolationPostProcessor> postProcessors,
                boolean debugEnabled,
                StringSearchModelInterpolator modelInterpolator,
                Logger logger) {
            this.valueSources = valueSources;
            this.postProcessors = postProcessors;
            this.debugEnabled = debugEnabled;

            this.interpolationTargets = new LinkedList<>();
            interpolationTargets.add(target);

            this.modelInterpolator = modelInterpolator;
            this.logger = logger;
        }

        public ModelInterpolationException run() {
            while (!interpolationTargets.isEmpty()) {
                Object obj = interpolationTargets.removeFirst();

                try {
                    traverseObjectWithParents(obj.getClass(), obj);
                } catch (ModelInterpolationException e) {
                    return e;
                }
            }

            return null;
        }

        @SuppressWarnings({"unchecked", "checkstyle:methodlength"})
        private void traverseObjectWithParents(Class<?> cls, Object target) throws ModelInterpolationException {
            if (cls == null) {
                return;
            }

            if (cls.isArray()) {
                evaluateArray(target);
            } else if (isQualifiedForInterpolation(cls)) {
                Field[] fields = FIELDS_BY_CLASS.computeIfAbsent(cls, k -> cls.getDeclaredFields());

                for (Field field : fields) {
                    Class<?> type = field.getType();
                    if (isQualifiedForInterpolation(field, type)) {
                        boolean isAccessible = field.isAccessible();
                        field.setAccessible(true);
                        try {
                            try {
                                if (String.class == type) {
                                    String value = (String) field.get(target);
                                    if (value != null) {
                                        String interpolated = modelInterpolator.interpolateInternal(
                                                value, valueSources, postProcessors, debugEnabled);

                                        if (!interpolated.equals(value)) {
                                            field.set(target, interpolated);
                                        }
                                    }
                                } else if (Collection.class.isAssignableFrom(type)) {
                                    Collection<Object> c = (Collection<Object>) field.get(target);
                                    if (c != null && !c.isEmpty()) {
                                        List<Object> originalValues = new ArrayList<>(c);
                                        try {
                                            c.clear();
                                        } catch (UnsupportedOperationException e) {
                                            if (debugEnabled && logger != null) {
                                                logger.debug("Skipping interpolation of field: " + field + " in: "
                                                        + cls.getName()
                                                        + "; it is an unmodifiable collection.");
                                            }
                                            continue;
                                        }

                                        for (Object value : originalValues) {
                                            if (value != null) {
                                                if (String.class == value.getClass()) {
                                                    String interpolated = modelInterpolator.interpolateInternal(
                                                            (String) value, valueSources, postProcessors, debugEnabled);

                                                    if (!interpolated.equals(value)) {
                                                        c.add(interpolated);
                                                    } else {
                                                        c.add(value);
                                                    }
                                                } else {
                                                    c.add(value);
                                                    if (value.getClass().isArray()) {
                                                        evaluateArray(value);
                                                    } else {
                                                        interpolationTargets.add(value);
                                                    }
                                                }
                                            } else {
                                                // add the null back in...not sure what else to do...
                                                c.add(value);
                                            }
                                        }
                                    }
                                } else if (Map.class.isAssignableFrom(type)) {
                                    Map<Object, Object> m = (Map<Object, Object>) field.get(target);
                                    if (m != null && !m.isEmpty()) {
                                        for (Map.Entry<Object, Object> entry : m.entrySet()) {
                                            Object value = entry.getValue();

                                            if (value != null) {
                                                if (String.class == value.getClass()) {
                                                    String interpolated = modelInterpolator.interpolateInternal(
                                                            (String) value, valueSources, postProcessors, debugEnabled);

                                                    if (!interpolated.equals(value)) {
                                                        try {
                                                            entry.setValue(interpolated);
                                                        } catch (UnsupportedOperationException e) {
                                                            if (debugEnabled && logger != null) {
                                                                logger.debug("Skipping interpolation of field: " + field
                                                                        + " (key: " + entry.getKey() + ") in: "
                                                                        + cls.getName()
                                                                        + "; it is an unmodifiable collection.");
                                                            }
                                                        }
                                                    }
                                                } else {
                                                    if (value.getClass().isArray()) {
                                                        evaluateArray(value);
                                                    } else {
                                                        interpolationTargets.add(value);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                } else {
                                    Object value = field.get(target);
                                    if (value != null) {
                                        if (field.getType().isArray()) {
                                            evaluateArray(value);
                                        } else {
                                            interpolationTargets.add(value);
                                        }
                                    }
                                }
                            } catch (IllegalArgumentException | IllegalAccessException e) {
                                throw new ModelInterpolationException(
                                        "Failed to interpolate field: " + field + " on class: " + cls.getName(), e);
                            }
                        } finally {
                            field.setAccessible(isAccessible);
                        }
                    }
                }

                traverseObjectWithParents(cls.getSuperclass(), target);
            }
        }

        private boolean isQualifiedForInterpolation(Class<?> cls) {
            return !cls.getPackage().getName().startsWith("java")
                    && !cls.getPackage().getName().startsWith("sun.nio.fs");
        }

        private boolean isQualifiedForInterpolation(Field field, Class<?> fieldType) {
            if (!PRIMITIVE_BY_CLASS.containsKey(fieldType)) {
                PRIMITIVE_BY_CLASS.put(fieldType, fieldType.isPrimitive());
            }

            if (PRIMITIVE_BY_CLASS.get(fieldType)) {
                return false;
            }

            //            if ( fieldType.isPrimitive() )
            //            {
            //                return false;
            //            }

            return !"parent".equals(field.getName());
        }

        private void evaluateArray(Object target) throws ModelInterpolationException {
            int len = Array.getLength(target);
            for (int i = 0; i < len; i++) {
                Object value = Array.get(target, i);
                if (value != null) {
                    if (String.class == value.getClass()) {
                        String interpolated = modelInterpolator.interpolateInternal(
                                (String) value, valueSources, postProcessors, debugEnabled);

                        if (!interpolated.equals(value)) {
                            Array.set(target, i, interpolated);
                        }
                    } else {
                        interpolationTargets.add(value);
                    }
                }
            }
        }
    }
}
