/*
 * 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 java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import jdk.internal.module.Modules;
import jdk.jfr.AnnotationElement;
import jdk.jfr.Enabled;
import jdk.jfr.Name;
import jdk.jfr.Period;
import jdk.jfr.SettingControl;
import jdk.jfr.SettingDefinition;
import jdk.jfr.StackTrace;
import jdk.jfr.Threshold;
import jdk.jfr.events.ActiveSettingEvent;
import jdk.jfr.internal.EventInstrumentation.SettingInfo;
import jdk.jfr.internal.settings.CutoffSetting;
import jdk.jfr.internal.settings.EnabledSetting;
import jdk.jfr.internal.settings.PeriodSetting;
import jdk.jfr.internal.settings.StackTraceSetting;
import jdk.jfr.internal.settings.ThresholdSetting;

// This class can't have a hard reference from PlatformEventType, since it
// holds SettingControl instances that need to be released
// when a class is unloaded (to avoid memory leaks).
public final class EventControl {
    final static class NamedControl {
        public final String name;
        public final Control control;
        NamedControl(String name, Control control) {
            this.name = name;
            this.control = control;
        }
    }
    static final String FIELD_SETTING_PREFIX = "setting";
    private static final Type TYPE_ENABLED = TypeLibrary.createType(EnabledSetting.class);
    private static final Type TYPE_THRESHOLD = TypeLibrary.createType(ThresholdSetting.class);
    private static final Type TYPE_STACK_TRACE = TypeLibrary.createType(StackTraceSetting.class);
    private static final Type TYPE_PERIOD = TypeLibrary.createType(PeriodSetting.class);
    private static final Type TYPE_CUTOFF = TypeLibrary.createType(CutoffSetting.class);

    private final ArrayList<SettingInfo> settingInfos = new ArrayList<>();
    private final ArrayList<NamedControl> namedControls = new ArrayList<>(5);
    private final PlatformEventType type;
    private final String idName;

    EventControl(PlatformEventType eventType) {
        addControl(Enabled.NAME, defineEnabled(eventType));
        if (eventType.hasDuration()) {
            addControl(Threshold.NAME, defineThreshold(eventType));
        }
        if (eventType.hasStackTrace()) {
            addControl(StackTrace.NAME, defineStackTrace(eventType));
        }
        if (eventType.hasPeriod()) {
            addControl(Period.NAME, definePeriod(eventType));
        }
        if (eventType.hasCutoff()) {
            addControl(Cutoff.NAME, defineCutoff(eventType));
        }

        ArrayList<AnnotationElement> aes = new ArrayList<>(eventType.getAnnotationElements());
        remove(eventType, aes, Threshold.class);
        remove(eventType, aes, Period.class);
        remove(eventType, aes, Enabled.class);
        remove(eventType, aes, StackTrace.class);
        remove(eventType, aes, Cutoff.class);
        aes.trimToSize();
        eventType.setAnnotations(aes);
        this.type = eventType;
        this.idName = String.valueOf(eventType.getId());
    }

    private boolean hasControl(String name) {
        for (NamedControl nc : namedControls) {
            if (name.equals(nc.name)) {
                return true;
            }
        }
        return false;
    }

    private void addControl(String name, Control control) {
        namedControls.add(new NamedControl(name, control));
    }

    static void remove(PlatformEventType type, List<AnnotationElement> aes, Class<? extends java.lang.annotation.Annotation> clazz) {
        long id = Type.getTypeId(clazz);
        for (AnnotationElement a : type.getAnnotationElements()) {
            if (a.getTypeId() == id && a.getTypeName().equals(clazz.getName())) {
                aes.remove(a);
            }
        }
    }

    EventControl(PlatformEventType es, Class<? extends jdk.internal.event.Event> eventClass) {
        this(es);
        defineSettings(eventClass);
    }

    @SuppressWarnings("unchecked")
    private void defineSettings(Class<?> eventClass) {
        // Iterate up the class hierarchy and let
        // subclasses shadow base classes.
        boolean allowPrivateMethod = true;
        while (eventClass != null) {
            for (Method m : eventClass.getDeclaredMethods()) {
                boolean isPrivate = Modifier.isPrivate(m.getModifiers());
                if (m.getReturnType() == Boolean.TYPE && m.getParameterCount() == 1 && (!isPrivate || allowPrivateMethod)) {
                    SettingDefinition se = m.getDeclaredAnnotation(SettingDefinition.class);
                    if (se != null) {
                        Class<?> settingClass = m.getParameters()[0].getType();
                        if (!Modifier.isAbstract(settingClass.getModifiers()) && SettingControl.class.isAssignableFrom(settingClass)) {
                            String name = m.getName();
                            Name n = m.getAnnotation(Name.class);
                            if (n != null) {
                                name = n.value();
                            }

                            if (!hasControl(name)) {
                                defineSetting((Class<? extends SettingControl>) settingClass, m, type, name);
                            }
                        }
                    }
                }
            }
            eventClass = eventClass.getSuperclass();
            allowPrivateMethod = false;
        }
    }

    private void defineSetting(Class<? extends SettingControl> settingsClass, Method method, PlatformEventType eventType, String settingName) {
        try {
            Module settingModule = settingsClass.getModule();
            Modules.addReads(settingModule, EventControl.class.getModule());
            int index = settingInfos.size();
            SettingInfo si = new SettingInfo(FIELD_SETTING_PREFIX + index, index);
            si.settingControl = instantiateSettingControl(settingsClass);
            Control c = si.settingControl;
            c.setDefault();
            String defaultValue = c.getValueSafe();
            if (defaultValue != null) {
                Type settingType = TypeLibrary.createType(settingsClass);
                ArrayList<AnnotationElement> aes = new ArrayList<>();
                for (Annotation a : method.getDeclaredAnnotations()) {
                    AnnotationElement ae = TypeLibrary.createAnnotation(a);
                    if (ae != null) {
                        aes.add(ae);
                    }
                }
                aes.trimToSize();
                addControl(settingName, si.settingControl);
                eventType.add(PrivateAccess.getInstance().newSettingDescriptor(settingType, settingName, defaultValue, aes));
                settingInfos.add(si);
            }
        } catch (InstantiationException e) {
            // Programming error by user, fail fast
            throw new InstantiationError("Could not instantiate setting " + settingsClass.getName() + " for event " + eventType.getLogName() + ". " + e.getMessage());
        } catch (IllegalAccessException e) {
            // Programming error by user, fail fast
            throw new IllegalAccessError("Could not access setting " + settingsClass.getName() + " for event " + eventType.getLogName() + ". " + e.getMessage());
        }
    }

    private SettingControl instantiateSettingControl(Class<? extends SettingControl> settingControlClass) throws IllegalAccessException, InstantiationException {
        SecuritySupport.makeVisibleToJFR(settingControlClass);
        final Constructor<?> cc;
        try {
            cc = settingControlClass.getDeclaredConstructors()[0];
        } catch (Exception e) {
            throw (Error) new InternalError("Could not get constructor for " + settingControlClass.getName()).initCause(e);
        }
        SecuritySupport.setAccessible(cc);
        try {
            return (SettingControl) cc.newInstance();
        } catch (IllegalArgumentException | InvocationTargetException e) {
            throw (Error) new InternalError("Could not instantiate setting for class " + settingControlClass.getName());
        }
    }

    private static Control defineEnabled(PlatformEventType type) {
        Enabled enabled = type.getAnnotation(Enabled.class);
        // Java events are enabled by default,
        // JVM events are not, maybe they should be? Would lower learning curve
        // there too.
        String def = type.isJVM() ? "false" : "true";
        if (enabled != null) {
            def = Boolean.toString(enabled.value());
        }
        type.add(PrivateAccess.getInstance().newSettingDescriptor(TYPE_ENABLED, Enabled.NAME, def, Collections.emptyList()));
        return new EnabledSetting(type, def);
    }

    private static Control defineThreshold(PlatformEventType type) {
        Threshold threshold = type.getAnnotation(Threshold.class);
        String def = "0 ns";
        if (threshold != null) {
            def = threshold.value();
        }
        type.add(PrivateAccess.getInstance().newSettingDescriptor(TYPE_THRESHOLD, Threshold.NAME, def, Collections.emptyList()));
        return new ThresholdSetting(type, def);
    }

    private static Control defineStackTrace(PlatformEventType type) {
        StackTrace stackTrace = type.getAnnotation(StackTrace.class);
        String def = "true";
        if (stackTrace != null) {
            def = Boolean.toString(stackTrace.value());
        }
        type.add(PrivateAccess.getInstance().newSettingDescriptor(TYPE_STACK_TRACE, StackTrace.NAME, def, Collections.emptyList()));
        return new StackTraceSetting(type, def);
    }

    private static Control defineCutoff(PlatformEventType type) {
        Cutoff cutoff = type.getAnnotation(Cutoff.class);
        String def = Cutoff.INIFITY;
        if (cutoff != null) {
            def = cutoff.value();
        }
        type.add(PrivateAccess.getInstance().newSettingDescriptor(TYPE_CUTOFF, Cutoff.NAME, def, Collections.emptyList()));
        return new CutoffSetting(type, def);
    }


    private static Control definePeriod(PlatformEventType type) {
        Period period = type.getAnnotation(Period.class);
        String def = "everyChunk";
        if (period != null) {
            def = period.value();
        }
        type.add(PrivateAccess.getInstance().newSettingDescriptor(TYPE_PERIOD, PeriodSetting.NAME, def, Collections.emptyList()));
        return new PeriodSetting(type, def);
    }

    void disable() {
        for (NamedControl nc : namedControls) {
            if (nc.control instanceof EnabledSetting) {
                nc.control.setValueSafe("false");
                return;
            }
        }
    }

    void writeActiveSettingEvent() {
        if (!type.isRegistered()) {
            return;
        }
        ActiveSettingEvent event = ActiveSettingEvent.EVENT.get();
        for (NamedControl nc : namedControls) {
            if (Utils.isSettingVisible(nc.control, type.hasEventHook())) {
                String value = nc.control.getLastValue();
                if (value == null) {
                    value = nc.control.getDefaultValue();
                }
                event.id = type.getId();
                event.name = nc.name;
                event.value = value;
                event.commit();
            }
        }
    }

    public ArrayList<NamedControl> getNamedControls() {
        return namedControls;
    }

    public PlatformEventType getEventType() {
        return type;
    }

    public String getSettingsId() {
        return idName;
    }

    public List<SettingInfo> getSettingInfos() {
        return settingInfos;
    }
}
