/**
 * 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.geronimo.microprofile.reporter.storage.templating;

import static java.util.Locale.ROOT;
import static java.util.stream.Collectors.joining;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

@ApplicationScoped
public class TemplatingEngine {
    private final ConcurrentMap<AccessorKey, Function<Object, Object>> accessors = new ConcurrentHashMap<>();

    private final ConcurrentMap<TemplateKey, Collection<Function<Object, String>>> templates = new ConcurrentHashMap<>();

    @Inject
    private TemplateHelper templateHelper;

    // simple passthrough impl with these specificites
    // - @include(template)
    // - @include(template,newModel1=someDataToPassthrough1,newModel=2someDataToPassthrough1)
    // - @each($collectionVar,templatePath)
    // - $var from data with dot notation support
    public Function<Object, String> compileIfNeeded(final String template, final Function<String, String> templateLoader) {
        final Collection<Function<Object, String>> segments = templates.computeIfAbsent(new TemplateKey(templateLoader, template),
                key -> precompile(key.template, key.loader));
        return data -> segments.stream().map(it -> it.apply(data)).collect(joining());
    }

    private Collection<Function<Object, String>> precompile(final String template,
            final Function<String, String> templateLoader) {
        final Collection<Function<Object, String>> segments = new ArrayList<>();

        final StringBuilder builder = new StringBuilder();
        boolean escaped = false;
        final char[] chars = template.toCharArray();
        String substring;
        for (int i = 0; i < chars.length; i++) {
            final char current = chars[i];
            if (escaped) {
                builder.append(current);
                escaped = false;
            } else if (current == '\\') { // escaping
                escaped = true;
            } else if (current == '$') { // variable
                final String value = builder.toString();
                segments.add(ctx -> value);
                builder.setLength(0);

                final StringBuilder variable = new StringBuilder();
                for (int j = i + 1; j < chars.length; j++) {
                    if (!Character.isJavaIdentifierPart(chars[j]) && chars[j] != '.') {
                        break;
                    }
                    variable.append(chars[j]);
                }
                i += variable.length();
                final String varName = variable.toString();
                segments.add(data -> {
                    final Object interpolated = interpolate(varName, data);
                    if (interpolated != null) {
                        return String.valueOf(interpolated);
                    }
                    return "";
                });
            } else if ((substring = template.substring(i)).startsWith("/*")) { // comment
                final int end = template.indexOf("*/", i);
                if (end < 0) {
                    throw new IllegalArgumentException("No comment end at index " + i + " for:\n" + template);
                }
                i = end + "*/".length();
            } else if (substring.startsWith("@include(")) {
                final String value = builder.toString();
                segments.add(data -> value);
                builder.setLength(0);

                final int end = findEndingParenthesis(chars, i + "@include(".length() + 1);
                if (end < 0) {
                    throw new IllegalArgumentException("Missing ')' token for @include at position " + i + " for:\n" + template);
                }
                final String tplPath = template.substring(i + "@include(".length(), end);
                i = end;
                segments.add(data -> {
                    final String interpolated = compileIfNeeded(tplPath, templateLoader).apply(data); // todo: compose segments
                    if (interpolated == null) {
                        return "";
                    }

                    final Object includeData;
                    final String templatePath;
                    if (interpolated.contains(",")) {
                        final String[] split = interpolated.split(",");
                        templatePath = split[0];

                        final Map<String, Object> map = new HashMap<>();
                        includeData = map;
                        for (int j = 1; j < split.length; j++) {
                            final String[] config = split[j].split("=");
                            if (config.length != 2) {
                                throw new IllegalArgumentException(
                                        "Passed data during a directive (@include) must set their alias, ex: name=foo.bar");
                            }
                            map.put(config[0], interpolate(config[1], data));
                        }
                    } else {
                        templatePath = interpolated;
                        includeData = data;
                    }

                    return compileIfNeeded(templateLoader.apply(templatePath), templateLoader).apply(includeData);
                });
            } else if (substring.startsWith("@escape(")) {
                i = handleFn("escape", template, templateLoader, segments, builder, chars, i, templateHelper::escape);
            } else if (substring.startsWith("@attributify(")) {
                i = handleFn("attributify", template, templateLoader, segments, builder, chars, i,
                        v -> v.toLowerCase(ROOT).replace(' ', '-'));
            } else if (substring.startsWith("@url(")) {
                i = handleFn("url", template, templateLoader, segments, builder, chars, i, v -> {
                    try {
                        return URLEncoder.encode(v, "UTF-8");
                    } catch (final UnsupportedEncodingException e) {
                        throw new IllegalStateException(e);
                    }
                });
            } else if (substring.startsWith("@lowercase(")) {
                i = handleFn("lowercase", template, templateLoader, segments, builder, chars, i, v -> v.toLowerCase(ROOT));
            } else if (substring.startsWith("@each(")) {
                final String value = builder.toString();
                segments.add(ctx -> value);
                builder.setLength(0);

                final int end = findEndingParenthesis(chars, i + "@each(".length() + 1);
                if (end < 0) {
                    throw new IllegalArgumentException("Missing ')' token for @each at position " + i +
                            " for:\n" + template);
                }

                final int startConfig = i + "@each(".length();
                final String config = template.substring(startConfig, end);
                i = end;

                final int sep = config.indexOf(",");
                if (sep < 0) {
                    throw new IllegalArgumentException(
                            "Bad configuration for @each, first parameter is the variable, second the template at index " +
                                    i + ", for:\n" + template);
                }

                final String variableName = config.substring(config.startsWith("$") ? 1 : 0, sep);
                final Function<Object, String> tplProvider;
                final String tpl = config.substring(sep + 1);
                if (tpl.startsWith("inline:")) {
                    final String completeTpl = tpl.substring("inline:".length());
                    tplProvider = data -> completeTpl;
                } else {
                    tplProvider = data -> templateLoader.apply(compileIfNeeded(tpl, templateLoader).apply(data));
                }
                segments.add(data -> {
                    final Object collection = interpolate(variableName, data);
                    if (collection == null) {
                        return "";
                    }
                    final Iterator<?> it;
                    if (Collection.class.isInstance(collection)) {
                        it = ((Collection<Object>) collection).iterator();
                    } else if (Map.class.isInstance(collection)) {
                        it = ((Map<Object, Object>) collection).entrySet().iterator();
                    } else {
                        throw new IllegalArgumentException("Only Collection and Map can be used in @each, got " + collection);
                    }
                    final String compiled = tplProvider.apply(data);
                    final StringBuilder out = new StringBuilder();
                    while (it.hasNext()) {
                        final Object next = it.next();
                        final boolean hasNext = it.hasNext();
                        final Map<String, Object> subData = new HashMap<>();
                        subData.put("$value", next);
                        subData.put("hasNext", hasNext);
                        out.append(compileIfNeeded(compiled, templateLoader).apply(subData));
                    }
                    return out.toString();
                });
            } else if (substring.startsWith("@if(")) {
                final String value = builder.toString();
                segments.add(ctx -> value);
                builder.setLength(0);

                final int end = findEndingParenthesis(chars, i + "@if(".length() + 1);
                if (end < 0) {
                    throw new IllegalArgumentException("Missing ')' token for @if at position " + i +
                            " for:\n" + template);
                }

                final String config = template.substring(i + "@if(".length(), end);
                i = end;

                final int sep = config.indexOf(",");
                if (sep < 0) {
                    throw new IllegalArgumentException(
                            "Bad configuration for @if, first parameter is the falsy condition, second the template. At index " +
                                    i + ", for:\n" + template);
                }

                final String variableName = config.substring(config.startsWith("$") ? 1 : 0, sep);
                final String tpl = config.substring(sep + 1);
                segments.add(data -> {
                    final Object condition = interpolate(variableName, data);
                    if (condition == null) {
                        return "";
                    }
                    final String conditionStr = String.valueOf(condition);
                    if ("false".equalsIgnoreCase(conditionStr) || conditionStr.isEmpty()) {
                        return "";
                    }

                    final String compiled = tpl.startsWith("inline:") ?
                            tpl.substring("inline:".length()) :
                            templateLoader.apply(compileIfNeeded(tpl, templateLoader).apply(data));
                    return compileIfNeeded(compiled, templateLoader).apply(data);
                });
            } else {
                builder.append(current);
            }
        }

        if (builder.length() > 0) {
            final String value = builder.toString();
            segments.add(ctx -> value);
        }

        return segments;
    }

    private int handleFn(final String name, final String template, final Function<String, String> templateLoader,
                         final Collection<Function<Object, String>> segments, final StringBuilder builder,
                         final char[] chars, final int currentIndex, final Function<String, String> impl) {
        final String value = builder.toString();
        segments.add(data -> value);
        builder.setLength(0);

        final int end = findEndingParenthesis(chars, currentIndex + name .length() + 2 /*@ and (*/ + 1);
        if (end < 0) {
            throw new IllegalArgumentException("Missing ')' token for @" + name + " at position " + currentIndex + " for:\n" + template);
        }
        final String toEscape = template.substring(currentIndex + name.length() + 2, end);
        segments.add(data -> {
            final String escapableValue = compileIfNeeded(toEscape, templateLoader).apply(data);
            if (escapableValue == null) {
                return "";
            }
            return impl.apply(escapableValue);
        });
        return end;
    }

    private int findEndingParenthesis(final char[] chars, final int from) {
        int remaining = 1;
        for (int i = from; i < chars.length; i++) {
            if (chars[i] == ')' && --remaining == 0) {
                return i;
            } else if (chars[i] == '(') {
                remaining++;
            }
        }
        return -1;
    }

    private Object getVariable(final Object registry, final String name) {
        if (registry == null) {
            return registry;
        }
        // map handling
        if (Map.class.isInstance(registry)) {
            return Map.class.cast(registry).get(name);
        }

        final Class<?> registryClass = registry.getClass();

        // array handling - foo.1.name syntax
        if (registryClass.isArray()) {
            return Array.get(registry, Integer.parseInt(name));
        }

        return accessors.computeIfAbsent(new AccessorKey(registryClass, name), key -> {
            // try getter
            try {
                final Method method = key.type
                        .getMethod("get" + Character.toUpperCase(key.name.charAt(0)) + key.name.substring(1));
                if (!method.isAccessible()) {
                    method.setAccessible(true);
                }
                return o -> {
                    try {
                        return method.invoke(o);
                    } catch (final IllegalAccessException e) {
                        throw new IllegalStateException(e);
                    } catch (final InvocationTargetException e) {
                        throw new IllegalStateException(e.getTargetException());
                    }
                };
            } catch (final NoSuchMethodException e) {
                // no-op
            }
            // try field
            try {
                final Field field = key.type.getDeclaredField(key.name);
                if (!field.isAccessible()) {
                    field.setAccessible(true);
                }
                return o -> {
                    try {
                        return field.get(o);
                    } catch (final IllegalAccessException e) {
                        throw new IllegalStateException(e);
                    }
                };
            } catch (final Exception e) {
                // no-op
            }
            return o -> null;
        }).apply(registry);
    }

    private Object interpolate(final String string, final Object data) {
        final String[] segments = string.split("\\.");
        Object registry = data;
        for (final String it : segments) {
            final Object variable = getVariable(registry, it);
            if (variable == null) {
                return null;
            }
            registry = variable;
        }
        return registry;
    }

    public void clean() {
        templates.clear();
    }

    private static class TemplateContext {

        private final Function<String, String> loader;

        private final Object data;

        private TemplateContext(final Function<String, String> loader, final Object data) {
            this.loader = loader;
            this.data = data;
        }
    }

    private static class AccessorKey {

        private final Class<?> type;

        private final String name;

        private final int hash;

        private AccessorKey(final Class<?> type, final String name) {
            this.type = type;
            this.name = name;
            this.hash = Objects.hash(type, name);
        }

        @Override
        public boolean equals(final Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || AccessorKey.class != o.getClass()) {
                return false;
            }
            final AccessorKey that = AccessorKey.class.cast(o);
            return Objects.equals(type, that.type) && Objects.equals(name, that.name);
        }

        @Override
        public int hashCode() {
            return hash;
        }
    }

    private static class TemplateKey {

        private final Function<String, String> loader;

        private final String template;

        private final int hash;

        private TemplateKey(final Function<String, String> loader, final String value) {
            this.loader = loader;
            this.template = value;
            this.hash = Objects.hash(loader, value);
        }

        @Override
        public boolean equals(final Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || TemplateKey.class != o.getClass()) {
                return false;
            }
            final TemplateKey that = TemplateKey.class.cast(o);
            return Objects.equals(template, that.template) && Objects.equals(loader, that.loader);
        }

        @Override
        public int hashCode() {
            return hash;
        }
    }
}
