/*
 *  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
 *
 *      https://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.ant.s3;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.time.Duration;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.lang3.reflect.TypeUtils;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;

import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.utils.AttributeMap;

/**
 * Static utility class for conversions from {@link String} to needed types.
 */
class StringConversions {
    private static final TypeVariable<?> ATTRIBUTE_KEY_TYPE = AttributeMap.Key.class.getTypeParameters()[0];

    private static final Map<Class<?>, Function<String, ?>> CONVERTERS;

    private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_WRAPPER =
        Stream
            .of(Byte.class, Short.class, Integer.class, Character.class, Long.class, Float.class, Double.class,
                Boolean.class)
            .collect(Collectors.collectingAndThen(Collectors.<Class<?>, Class<?>, Class<?>> toMap(t -> {
                try {
                    return (Class<?>) t.getDeclaredField("TYPE").get(null);
                } catch (IllegalAccessException | NoSuchFieldException e) {
                    throw new IllegalStateException(e);
                }
            }, Function.identity()), Collections::unmodifiableMap));

    static {
        final Map<Class<?>, Function<String, ?>> cnv = new LinkedHashMap<>();
        cnv.put(Byte.class, Byte::valueOf);
        cnv.put(Short.class, Short::valueOf);
        cnv.put(Integer.class, Integer::valueOf);
        cnv.put(Character.class, s -> s.charAt(0));
        cnv.put(Long.class, Long::valueOf);
        cnv.put(Float.class, Float::valueOf);
        cnv.put(Double.class, Double::valueOf);
        cnv.put(Boolean.class, Boolean::valueOf);
        cnv.put(String.class, Function.identity());
        cnv.put(Region.class, Region::of);
        cnv.put(Duration.class, Duration::parse);
        CONVERTERS = Collections.unmodifiableMap(cnv);
    }

    private static Field keyField(Class<? extends AttributeMap.Key<?>> keyType, String name) {
        try {
            final Field result = keyType.getDeclaredField(name.toUpperCase(Locale.US));
            Exceptions.raiseUnless(Modifier.isStatic(result.getModifiers()) && result.getType().equals(keyType),
                IllegalArgumentException::new,
                () -> String.format("Illegal %s key: %s", keyType.getSimpleName(), name));
            return result;
        } catch (NoSuchFieldException | SecurityException e) {
            throw new BuildException(e);
        }
    }

    /**
     * Convert {@code value} to {@code type}.
     *
     * @param type
     * @param value
     * @return T
     */
    static <T> T as(Class<?> type, String value) {
        if (type.isPrimitive()) {
            type = PRIMITIVE_TO_WRAPPER.get(type);
        }
        final Optional<Object> converted = Optional.of(type).map(CONVERTERS::get).map(fn -> fn.apply(value));

        if (converted.isPresent()) {
            @SuppressWarnings("unchecked")
            final T result = (T) converted.get();
            return result;
        }
        if (type.isEnum()) {
            try {
                @SuppressWarnings({ "unchecked", "rawtypes" })
                final T result = (T) Enum.valueOf((Class) type, value);
                return result;
            } catch (IllegalArgumentException e) {
            }
            @SuppressWarnings({ "unchecked", "rawtypes" })
            final T result = (T) Enum.valueOf((Class) type, value.toUpperCase(Locale.US));
            return result;
        }
        // Ant conventions
        Constructor<T> ctor;
        try {
            @SuppressWarnings("unchecked")
            final Constructor<T> _ctor = (Constructor<T>) type.getDeclaredConstructor(Project.class, String.class);
            ctor = _ctor;
        } catch (NoSuchMethodException | SecurityException e) {
            try {
                @SuppressWarnings("unchecked")
                final Constructor<T> _ctor = (Constructor<T>) type.getDeclaredConstructor(String.class);
                ctor = _ctor;
            } catch (NoSuchMethodException | SecurityException e2) {
                ctor = null;
            }
        }
        if (ctor != null) {
            try {
                return ctor.newInstance(value);
            } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
                throw new IllegalStateException(e);
            }
        }
        throw new IllegalArgumentException();
    }

    /**
     * Generate an AWS SDK {@link AttributeMap} from the specified
     * {@link String} {@link Map} for the specified key type.
     *
     * @param <K>
     * @param keyType
     * @param m
     * @return {@link AttributeMap}
     */
    static <K extends AttributeMap.Key<?>> AttributeMap attributes(Class<K> keyType, Map<String, String> m) {
        final AttributeMap.Builder b = AttributeMap.builder();

        m.forEach((k, v) -> {
            final Field keyField = keyField(keyType, k);
            final AttributeMap.Key<Object> key;
            try {
                @SuppressWarnings("unchecked")
                final AttributeMap.Key<Object> _key = (AttributeMap.Key<Object>) keyField.get(null);
                key = _key;
            } catch (IllegalArgumentException | IllegalAccessException e) {
                throw new BuildException(e);
            }
            final Type valueType =
                TypeUtils.getTypeArguments(keyField.getGenericType(), AttributeMap.Key.class).get(ATTRIBUTE_KEY_TYPE);

            final Object value = as(TypeUtils.getRawType(valueType, null), v);

            b.<Object> put(key, value);
        });

        return b.build();
    }
}
