/*
 * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.jfr.internal;

import static java.util.concurrent.TimeUnit.MICROSECONDS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;

import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.nio.file.Path;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
import jdk.jfr.Event;
import jdk.jfr.FlightRecorderPermission;
import jdk.jfr.Recording;
import jdk.jfr.RecordingState;
import jdk.jfr.internal.handlers.EventHandler;
import jdk.jfr.internal.settings.PeriodSetting;
import jdk.jfr.internal.settings.StackTraceSetting;
import jdk.jfr.internal.settings.ThresholdSetting;

public final class Utils {

    private static final Object flushObject = new Object();
    private static final String INFINITY = "infinity";
    public static final String EVENTS_PACKAGE_NAME = "jdk.jfr.events";
    public static final String INSTRUMENT_PACKAGE_NAME = "jdk.jfr.internal.instrument";
    public static final String HANDLERS_PACKAGE_NAME = "jdk.jfr.internal.handlers";
    public static final String REGISTER_EVENT = "registerEvent";
    public static final String ACCESS_FLIGHT_RECORDER = "accessFlightRecorder";
    private final static String LEGACY_EVENT_NAME_PREFIX = "com.oracle.jdk.";

    private static Boolean SAVE_GENERATED;


    public static void checkAccessFlightRecorder() throws SecurityException {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new FlightRecorderPermission(ACCESS_FLIGHT_RECORDER));
        }
    }

    public static void checkRegisterPermission() throws SecurityException {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new FlightRecorderPermission(REGISTER_EVENT));
        }
    }

    private static enum TimespanUnit {
        NANOSECONDS("ns", 1000), MICROSECONDS("us", 1000), MILLISECONDS("ms", 1000), SECONDS("s", 60), MINUTES("m", 60), HOURS("h", 24), DAYS("d", 7);

        final String text;
        final long amount;

        TimespanUnit(String unit, long amount) {
            this.text = unit;
            this.amount = amount;
        }
    }

    // Tjis method can't handle Long.MIN_VALUE because absolute value is negative
    private static String formatDataAmount(String formatter, long amount) {
        int exp = (int) (Math.log(Math.abs(amount)) / Math.log(1024));
        char unitPrefix = "kMGTPE".charAt(exp - 1);
        return String.format(formatter, amount / Math.pow(1024, exp), unitPrefix);
    }

    public static String formatBytesCompact(long bytes) {
        if (bytes < 1024) {
            return String.valueOf(bytes);
        }
        return formatDataAmount("%.1f%cB", bytes);
    }

    public static String formatBits(long bits) {
        if (bits == 1 || bits == -1) {
            return bits + " bit";
        }
        if (bits < 1024 && bits > -1024) {
            return bits + " bits";
        }
        return formatDataAmount("%.1f %cbit", bits);
    }

    public static String formatBytes(long bytes) {
        if (bytes == 1 || bytes == -1) {
            return bytes + " byte";
        }
        if (bytes < 1024 && bytes > -1024) {
            return bytes + " bytes";
        }
        return formatDataAmount("%.1f %cB", bytes);
    }

    public static String formatBytesPerSecond(long bytes) {
        if (bytes < 1024 && bytes > -1024) {
            return bytes + " byte/s";
        }
        return formatDataAmount("%.1f %cB/s", bytes);
    }

    public static String formatBitsPerSecond(long bits) {
        if (bits < 1024 && bits > -1024) {
            return bits + " bps";
        }
        return formatDataAmount("%.1f %cbps", bits);
    }
    public static String formatTimespan(Duration dValue, String separation) {
        if (dValue == null) {
            return "0";
        }
        long value = dValue.toNanos();
        TimespanUnit result = TimespanUnit.NANOSECONDS;
        for (TimespanUnit unit : TimespanUnit.values()) {
            result = unit;
            long amount = unit.amount;
            if (result == TimespanUnit.DAYS || value < amount || value % amount != 0) {
                break;
            }
            value /= amount;
        }
        return String.format("%d%s%s", value, separation, result.text);
    }

    public static long parseTimespanWithInfinity(String s) {
        if (INFINITY.equals(s)) {
            return Long.MAX_VALUE;
        }
        return parseTimespan(s);
    }

    public static long parseTimespan(String s) {
        if (s.endsWith("ns")) {
            return Long.parseLong(s.substring(0, s.length() - 2).trim());
        }
        if (s.endsWith("us")) {
            return NANOSECONDS.convert(Long.parseLong(s.substring(0, s.length() - 2).trim()), MICROSECONDS);
        }
        if (s.endsWith("ms")) {
            return NANOSECONDS.convert(Long.parseLong(s.substring(0, s.length() - 2).trim()), MILLISECONDS);
        }
        if (s.endsWith("s")) {
            return NANOSECONDS.convert(Long.parseLong(s.substring(0, s.length() - 1).trim()), SECONDS);
        }
        if (s.endsWith("m")) {
            return 60 * NANOSECONDS.convert(Long.parseLong(s.substring(0, s.length() - 1).trim()), SECONDS);
        }
        if (s.endsWith("h")) {
            return 60 * 60 * NANOSECONDS.convert(Long.parseLong(s.substring(0, s.length() - 1).trim()), SECONDS);
        }
        if (s.endsWith("d")) {
            return 24 * 60 * 60 * NANOSECONDS.convert(Long.parseLong(s.substring(0, s.length() - 1).trim()), SECONDS);
        }

        try {
            Long.parseLong(s);
        } catch (NumberFormatException nfe) {
            throw new NumberFormatException("'" + s + "' is not a valid timespan. Shoule be numeric value followed by a unit, i.e. 20 ms. Valid units are ns, us, s, m, h and d.");
        }
        // Only accept values with units
        throw new NumberFormatException("Timespan + '" + s + "' is missing unit. Valid units are ns, us, s, m, h and d.");
    }

    /**
     * Return all annotations as they are visible in the source code
     *
     * @param clazz class to return annotations from
     *
     * @return list of annotation
     *
     */
    static List<Annotation> getAnnotations(Class<?> clazz) {
        List<Annotation> annos = new ArrayList<>();
        for (Annotation a : clazz.getAnnotations()) {
            annos.addAll(getAnnotation(a));
        }
        return annos;
    }

    private static List<? extends Annotation> getAnnotation(Annotation a) {
        Class<?> annotated = a.annotationType();
        Method valueMethod = getValueMethod(annotated);
        if (valueMethod != null) {
            Class<?> returnType = valueMethod.getReturnType();
            if (returnType.isArray()) {
                Class<?> candidate = returnType.getComponentType();
                Repeatable r = candidate.getAnnotation(Repeatable.class);
                if (r != null) {
                    Class<?> repeatClass = r.value();
                    if (annotated == repeatClass) {
                        return getAnnotationValues(a, valueMethod);
                    }
                }
            }
        }
        List<Annotation> annos = new ArrayList<>();
        annos.add(a);
        return annos;
    }

    static boolean isAfter(RecordingState stateToTest, RecordingState b) {
        return stateToTest.ordinal() > b.ordinal();
    }

    static boolean isBefore(RecordingState stateToTest, RecordingState b) {
        return stateToTest.ordinal() < b.ordinal();
    }

    static boolean isState(RecordingState stateToTest, RecordingState... states) {
        for (RecordingState s : states) {
            if (s == stateToTest) {
                return true;
            }
        }
        return false;
    }

    private static List<Annotation> getAnnotationValues(Annotation a, Method valueMethod) {
        try {
            return Arrays.asList((Annotation[]) valueMethod.invoke(a, new Object[0]));
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            return new ArrayList<>();
        }
    }

    private static Method getValueMethod(Class<?> annotated) {
        try {
            return annotated.getMethod("value", new Class<?>[0]);
        } catch (NoSuchMethodException e) {
            return null;
        }
    }

    public static void touch(Path dumpFile) throws IOException {
        RandomAccessFile raf = new RandomAccessFile(dumpFile.toFile(), "rw");
        raf.close();
    }

    public static Class<?> unboxType(Class<?> t) {
        if (t == Integer.class) {
            return int.class;
        }
        if (t == Long.class) {
            return long.class;
        }
        if (t == Float.class) {
            return float.class;
        }
        if (t == Double.class) {
            return double.class;
        }
        if (t == Byte.class) {
            return byte.class;
        }
        if (t == Short.class) {
            return short.class;
        }
        if (t == Boolean.class) {
            return boolean.class;
        }
        if (t == Character.class) {
            return char.class;
        }
        return t;
    }

    static long nanosToTicks(long nanos) {
        return (long) (nanos * JVM.getJVM().getTimeConversionFactor());
    }

    static synchronized EventHandler getHandler(Class<? extends jdk.internal.event.Event> eventClass) {
        Utils.ensureValidEventSubclass(eventClass);
        try {
            Field f = eventClass.getDeclaredField(EventInstrumentation.FIELD_EVENT_HANDLER);
            SecuritySupport.setAccessible(f);
            return (EventHandler) f.get(null);
        } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
            throw new InternalError("Could not access event handler");
        }
    }

    static synchronized void setHandler(Class<? extends jdk.internal.event.Event> eventClass, EventHandler handler) {
        Utils.ensureValidEventSubclass(eventClass);
        try {
            Field field = eventClass.getDeclaredField(EventInstrumentation.FIELD_EVENT_HANDLER);
            SecuritySupport.setAccessible(field);
            field.set(null, handler);
        } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
            throw new InternalError("Could not access event handler");
        }
    }

    public static Map<String, String> sanitizeNullFreeStringMap(Map<String, String> settings) {
        HashMap<String, String> map = new HashMap<>(settings.size());
        for (Map.Entry<String, String> e : settings.entrySet()) {
            String key = e.getKey();
            if (key == null) {
                throw new NullPointerException("Null key is not allowed in map");
            }
            String value = e.getValue();
            if (value == null) {
                throw new NullPointerException("Null value is not allowed in map");
            }
            map.put(key, value);
        }
        return map;
    }

    public static <T> List<T> sanitizeNullFreeList(List<T> elements, Class<T> clazz) {
        List<T> sanitized = new ArrayList<>(elements.size());
        for (T element : elements) {
            if (element == null) {
                throw new NullPointerException("Null is not an allowed element in list");
            }
            if (element.getClass() != clazz) {
                throw new ClassCastException();
            }
            sanitized.add(element);
        }
        return sanitized;
    }

    static List<Field> getVisibleEventFields(Class<?> clazz) {
        Utils.ensureValidEventSubclass(clazz);
        List<Field> fields = new ArrayList<>();
        for (Class<?> c = clazz; c != jdk.internal.event.Event.class; c = c.getSuperclass()) {
            for (Field field : c.getDeclaredFields()) {
                // skip private field in base classes
                if (c == clazz || !Modifier.isPrivate(field.getModifiers())) {
                    fields.add(field);
                }
            }
        }
        return fields;
    }

    public static void ensureValidEventSubclass(Class<?> eventClass) {
        if (jdk.internal.event.Event.class.isAssignableFrom(eventClass) && Modifier.isAbstract(eventClass.getModifiers())) {
            throw new IllegalArgumentException("Abstract event classes are not allowed");
        }
        if (eventClass == Event.class || eventClass == jdk.internal.event.Event.class || !jdk.internal.event.Event.class.isAssignableFrom(eventClass)) {
            throw new IllegalArgumentException("Must be a subclass to " + Event.class.getName());
        }
    }

    public static void writeGeneratedASM(String className, byte[] bytes) {
        if (SAVE_GENERATED == null) {
            // We can't calculate value statically because it will force
            // initialization of SecuritySupport, which cause
            // UnsatisfiedLinkedError on JDK 8 or non-Oracle JDKs
            SAVE_GENERATED = SecuritySupport.getBooleanProperty("jfr.save.generated.asm");
        }
        if (SAVE_GENERATED) {
            try {
                try (FileOutputStream fos = new FileOutputStream(className + ".class")) {
                    fos.write(bytes);
                }

                try (FileWriter fw = new FileWriter(className + ".asm"); PrintWriter pw = new PrintWriter(fw)) {
                    ClassReader cr = new ClassReader(bytes);
                    CheckClassAdapter.verify(cr, true, pw);
                }
                Logger.log(LogTag.JFR_SYSTEM_BYTECODE, LogLevel.INFO, "Instrumented code saved to " + className + ".class and .asm");
            } catch (IOException e) {
                Logger.log(LogTag.JFR_SYSTEM_BYTECODE, LogLevel.INFO, "Could not save instrumented code, for " + className + ".class and .asm");
            }
        }
    }

    public static void ensureInitialized(Class<? extends jdk.internal.event.Event> eventClass) {
        SecuritySupport.ensureClassIsInitialized(eventClass);
    }

    public static Object makePrimitiveArray(String typeName, List<Object> values) {
        int length = values.size();
        switch (typeName) {
        case "int":
            int[] ints = new int[length];
            for (int i = 0; i < length; i++) {
                ints[i] = (int) values.get(i);
            }
            return ints;
        case "long":
            long[] longs = new long[length];
            for (int i = 0; i < length; i++) {
                longs[i] = (long) values.get(i);
            }
            return longs;

        case "float":
            float[] floats = new float[length];
            for (int i = 0; i < length; i++) {
                floats[i] = (float) values.get(i);
            }
            return floats;

        case "double":
            double[] doubles = new double[length];
            for (int i = 0; i < length; i++) {
                doubles[i] = (double) values.get(i);
            }
            return doubles;

        case "short":
            short[] shorts = new short[length];
            for (int i = 0; i < length; i++) {
                shorts[i] = (short) values.get(i);
            }
            return shorts;
        case "char":
            char[] chars = new char[length];
            for (int i = 0; i < length; i++) {
                chars[i] = (char) values.get(i);
            }
            return chars;
        case "byte":
            byte[] bytes = new byte[length];
            for (int i = 0; i < length; i++) {
                bytes[i] = (byte) values.get(i);
            }
            return bytes;
        case "boolean":
            boolean[] booleans = new boolean[length];
            for (int i = 0; i < length; i++) {
                booleans[i] = (boolean) values.get(i);
            }
            return booleans;
        case "java.lang.String":
            String[] strings = new String[length];
            for (int i = 0; i < length; i++) {
                strings[i] = (String) values.get(i);
            }
            return strings;
        }
        return null;
    }

    public static boolean isSettingVisible(Control c, boolean hasEventHook) {
        if (c instanceof ThresholdSetting) {
            return !hasEventHook;
        }
        if (c instanceof PeriodSetting) {
            return hasEventHook;
        }
        if (c instanceof StackTraceSetting) {
            return !hasEventHook;
        }
        return true;
    }

    public static boolean isSettingVisible(long typeId, boolean hasEventHook) {
        if (ThresholdSetting.isType(typeId)) {
            return !hasEventHook;
        }
        if (PeriodSetting.isType(typeId)) {
            return hasEventHook;
        }
        if (StackTraceSetting.isType(typeId)) {
            return !hasEventHook;
        }
        return true;
    }

    public static Type getValidType(Class<?> type, String name) {
        Objects.requireNonNull(type, "Null is not a valid type for value descriptor " + name);
        if (type.isArray()) {
            type = type.getComponentType();
            if (type != String.class && !type.isPrimitive()) {
                throw new IllegalArgumentException("Only arrays of primitives and Strings are allowed");
            }
        }

        Type knownType = Type.getKnownType(type);
        if (knownType == null || knownType == Type.STACK_TRACE) {
            throw new IllegalArgumentException("Only primitive types, java.lang.Thread, java.lang.String and java.lang.Class are allowed for value descriptors. " + type.getName());
        }
        return knownType;
    }

    public static <T> List<T> smallUnmodifiable(List<T> list) {
        if (list.isEmpty()) {
            return Collections.emptyList();
        }
        if (list.size() == 1) {
            return Collections.singletonList(list.get(0));
        }
        return Collections.unmodifiableList(list);
    }

    public static String upgradeLegacyJDKEvent(String eventName) {
        if (eventName.length() <= LEGACY_EVENT_NAME_PREFIX.length()) {
            return eventName;
        }
        if (eventName.startsWith(LEGACY_EVENT_NAME_PREFIX)) {
            int index = eventName.lastIndexOf(".");
            if (index == LEGACY_EVENT_NAME_PREFIX.length() - 1) {
                return Type.EVENT_NAME_PREFIX + eventName.substring(index + 1);
            }
        }
        return eventName;
    }

    public static void verifyMirror(Class<?> mirror, Class<?> real) {
        Class<?> cMirror = Objects.requireNonNull(mirror);
        Class<?> cReal = Objects.requireNonNull(real);

        while (cReal != null) {
            Map<String, Field> mirrorFields = new HashMap<>();
            if (cMirror != null) {
                for (Field f : cMirror.getDeclaredFields()) {
                    if (isSupportedType(f.getType())) {
                        mirrorFields.put(f.getName(), f);
                    }
                }
            }
            for (Field realField : cReal.getDeclaredFields()) {
                if (isSupportedType(realField.getType())) {
                    String fieldName = realField.getName();
                    Field mirrorField = mirrorFields.get(fieldName);
                    if (mirrorField == null) {
                        throw new InternalError("Missing mirror field for " + cReal.getName() + "#" + fieldName);
                    }
                    if (realField.getModifiers() != mirrorField.getModifiers()) {
                        throw new InternalError("Incorrect modifier for mirror field "+ cMirror.getName() + "#" + fieldName);
                    }
                    mirrorFields.remove(fieldName);
                }
            }
            if (!mirrorFields.isEmpty()) {
                throw new InternalError(
                        "Found additional fields in mirror class " + cMirror.getName() + " " + mirrorFields.keySet());
            }
            if (cMirror != null) {
                cMirror = cMirror.getSuperclass();
            }
            cReal = cReal.getSuperclass();
        }
    }

    private static boolean isSupportedType(Class<?> type) {
        if (Modifier.isTransient(type.getModifiers()) || Modifier.isStatic(type.getModifiers())) {
            return false;
        }
        return Type.isValidJavaFieldType(type.getName());
    }

    public static String makeFilename(Recording recording) {
        String pid = JVM.getJVM().getPid();
        String date = Repository.REPO_DATE_FORMAT.format(LocalDateTime.now());
        String idText = recording == null ? "" :  "-id-" + Long.toString(recording.getId());
        return "hotspot-" + "pid-" + pid + idText + "-" + date + ".jfr";
    }

    public static void takeNap(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            // ok
        }
    }

    public static void notifyFlush() {
        synchronized (flushObject) {
            flushObject.notifyAll();
        }
    }

    public static void waitFlush(long timeOut) {
        synchronized (flushObject) {
            try {
                flushObject.wait(timeOut);
            } catch (InterruptedException e) {
                // OK
            }
        }

    }

    public static long timeToNanos(Instant timestamp) {
        return timestamp.getEpochSecond() * 1_000_000_000L + timestamp.getNano();
    }
}
