/*
 * 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;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import jdk.jfr.internal.PlatformRecorder;
import jdk.jfr.internal.PlatformRecording;
import jdk.jfr.internal.Type;
import jdk.jfr.internal.Utils;
import jdk.jfr.internal.WriteableUserPath;

/**
 * Provides means to configure, start, stop and dump recording data to disk.
 * <p>
 * The following example shows how configure, start, stop and dump recording data to disk.
 *
 * <pre>
 * <code>
 *   Configuration c = Configuration.getConfiguration("default");
 *   Recording r = new Recording(c);
 *   r.start();
 *   System.gc();
 *   Thread.sleep(5000);
 *   r.stop();
 *   r.dump(Files.createTempFile("my-recording", ".jfr"));
 * </code>
 * </pre>
 *
 * @since 9
 */
public final class Recording implements Closeable {

    private static class RecordingSettings extends EventSettings {

        private final Recording recording;
        private final String identifier;

        RecordingSettings(Recording r, String identifier) {
            this.recording = r;
            this.identifier = identifier;
        }

        RecordingSettings(Recording r, Class<? extends Event> eventClass) {
            Utils.ensureValidEventSubclass(eventClass);
            this.recording = r;
            this.identifier = String.valueOf(Type.getTypeId(eventClass));
        }

        @Override
        public EventSettings with(String name, String value) {
            Objects.requireNonNull(value);
            recording.setSetting(identifier + "#" + name, value);
            return this;
        }

        @Override
        public Map<String, String> toMap() {
            return recording.getSettings();
        }
    }

    private final PlatformRecording internal;

    public Recording(Map<String, String> settings) {
        PlatformRecorder r = FlightRecorder.getFlightRecorder().getInternal();
        synchronized (r) {
            this.internal = r.newRecording(settings);
            this.internal.setRecording(this);
            if (internal.getRecording() != this) {
                throw new InternalError("Internal recording not properly setup");
            }
        }
    }

    /**
     * Creates a recording without any settings.
     * <p>
     * A newly created recording is in the {@link RecordingState#NEW} state. To start
     * the recording, invoke the {@link Recording#start()} method.
     *
     * @throws IllegalStateException if Flight Recorder can't be created (for
     *         example, if the Java Virtual Machine (JVM) lacks Flight Recorder
     *         support, or if the file repository can't be created or accessed)
     *
     * @throws SecurityException If a security manager is used and
     *         FlightRecorderPermission "accessFlightRecorder" is not set.
     */
    public Recording() {
        this(new HashMap<String, String>());
     }

    /**
     * Creates a recording with settings from a configuration.
     * <p>
     * The following example shows how create a recording that uses a predefined configuration.
     *
     * <pre>
     * <code>
     * Recording r = new Recording(Configuration.getConfiguration("default"));
     * </code>
     * </pre>
     *
     * The newly created recording is in the {@link RecordingState#NEW} state. To
     * start the recording, invoke the {@link Recording#start()} method.
     *
     * @param configuration configuration that contains the settings to be use, not
     *        {@code null}
     *
     * @throws IllegalStateException if Flight Recorder can't be created (for
     *         example, if the Java Virtual Machine (JVM) lacks Flight Recorder
     *         support, or if the file repository can't be created or accessed)
     *
     * @throws SecurityException if a security manager is used and
     *         FlightRecorderPermission "accessFlightRecorder" is not set.
     *
     * @see Configuration
     */
    public Recording(Configuration configuration) {
        this(configuration.getSettings());
    }

    /**
     * Starts this recording.
     * <p>
     * It's recommended that the recording options and event settings are configured
     * before calling this method. The benefits of doing so are a more consistent
     * state when analyzing the recorded data, and improved performance because the
     * configuration can be applied atomically.
     * <p>
     * After a successful invocation of this method, this recording is in the
     * {@code RUNNING} state.
     *
     * @throws IllegalStateException if recording is already started or is in the
     *         {@code CLOSED} state
     */
    public void start() {
        internal.start();
    }

    /**
     * Starts this recording after a delay.
     * <p>
     * After a successful invocation of this method, this recording is in the
     * {@code DELAYED} state.
     *
     * @param delay the time to wait before starting this recording, not
     *        {@code null}
     * @throws IllegalStateException if the recording is not it the {@code NEW} state
     */
    public void scheduleStart(Duration delay) {
        Objects.requireNonNull(delay);
        internal.scheduleStart(delay);
    }

    /**
     * Stops this recording.
     * <p>
     * When a recording is stopped it can't be restarted. If this
     * recording has a destination, data is written to that destination and
     * the recording is closed. After a recording is closed, the data is no longer
     * available.
     * <p>
     * After a successful invocation of this method, this recording will be
     * in the {@code STOPPED} state.
     *
     * @return {@code true} if recording is stopped, {@code false} otherwise
     *
     * @throws IllegalStateException if the recording is not started or is already stopped
     *
     * @throws SecurityException if a security manager exists and the caller
     *         doesn't have {@code FilePermission} to write to the destination
     *         path
     *
     * @see #setDestination(Path)
     *
     */
    public boolean stop() {
        return internal.stop("Stopped by user");
    }

    /**
     * Returns settings used by this recording.
     * <p>
     * Modifying the returned {@code Map} will not change the settings for this recording.
     * <p>
     * If no settings are set for this recording, an empty {@code Map} is
     * returned.
     *
     * @return recording settings, not {@code null}
     */
    public Map<String, String> getSettings() {
        return new HashMap<>(internal.getSettings());
    }

    /**
     * Returns the current size of this recording in the disk repository,
     * measured in bytes.
     * <p>
     * The size is updated when recording buffers are flushed. If the recording is
     * not written to the disk repository the returned size is always {@code 0}.
     *
     * @return amount of recorded data, measured in bytes, or {@code 0} if the
     *         recording is not written to the disk repository
     */
    public long getSize() {
        return internal.getSize();
    }

    /**
     * Returns the time when this recording was stopped.
     *
     * @return the time, or {@code null} if this recording is not stopped
     */
    public Instant getStopTime() {
        return internal.getStopTime();
    }

    /**
     * Returns the time when this recording was started.
     *
     * @return the the time, or {@code null} if this recording is not started
     */
    public Instant getStartTime() {
        return internal.getStartTime();
    }

    /**
     * Returns the maximum size, measured in bytes, at which data is no longer kept in the disk repository.
     *
     * @return maximum size in bytes, or {@code 0} if no maximum size is set
     */
    public long getMaxSize() {
        return internal.getMaxSize();
    }

    /**
     * Returns the length of time that the data is kept in the disk repository
     * before it is removed.
     *
     * @return maximum length of time, or {@code null} if no maximum length of time
     *         has been set
     */
    public Duration getMaxAge() {
        return internal.getMaxAge();
    }

    /**
     * Returns the name of this recording.
     * <p>
     * By default, the name is the same as the recording ID.
     *
     * @return the recording name, not {@code null}
     */
    public String getName() {
        return internal.getName();
    }

    /**
     * Replaces all settings for this recording.
     * <p>
     * The following example shows how to set event settings for a recording.
     *
     * <pre>
     * <code>
     *     Map{@literal <}String, String{@literal >} settings = new HashMap{@literal <}{@literal >}();
     *     settings.putAll(EventSettings.enabled("jdk.CPUSample").withPeriod(Duration.ofSeconds(2)).toMap());
     *     settings.putAll(EventSettings.enabled(MyEvent.class).withThreshold(Duration.ofSeconds(2)).withoutStackTrace().toMap());
     *     settings.put("jdk.ExecutionSample#period", "10 ms");
     *     recording.setSettings(settings);
     * </code>
     * </pre>
     *
     * The following example shows how to merge settings.
     *
     * <pre>
     *     {@code
     *     Map<String, String> settings = recording.getSettings();
     *     settings.putAll(additionalSettings);
     *     recording.setSettings(settings);
     * }
     * </pre>
     *
     * @param settings the settings to set, not {@code null}
     */
    public void setSettings(Map<String, String> settings) {
        Objects.requireNonNull(settings);
        Map<String, String> sanitized = Utils.sanitizeNullFreeStringMap(settings);
        internal.setSettings(sanitized);
    }

    /**
     * Returns the recording state that this recording is currently in.
     *
     * @return the recording state, not {@code null}
     *
     * @see RecordingState
     */
    public RecordingState getState() {
        return internal.getState();
    }

    /**
     * Releases all data that is associated with this recording.
     * <p>
     * After a successful invocation of this method, this recording is in the
     * {@code CLOSED} state.
     */
    @Override
    public void close() {
        internal.close();
    }

    /**
     * Returns a clone of this recording, with a new recording ID and name.
     *
     * Clones are useful for dumping data without stopping the recording. After
     * a clone is created, the amount of data to copy is constrained
     * with the {@link #setMaxAge(Duration)} method and the {@link #setMaxSize(long)}method.
     *
     * @param stop {@code true} if the newly created copy should be stopped
     *        immediately, {@code false} otherwise
     * @return the recording copy, not {@code null}
     */
    public Recording copy(boolean stop) {
        return internal.newCopy(stop);
    }

    /**
     * Writes recording data to a file.
     * <p>
     * Recording must be started, but not necessarily stopped.
     *
     * @param destination the location where recording data is written, not
     *        {@code null}
     *
     * @throws IOException if the recording can't be copied to the specified
     *         location
     *
     * @throws SecurityException if a security manager exists and the caller doesn't
     *         have {@code FilePermission} to write to the destination path
     */
    public void dump(Path destination) throws IOException {
        Objects.requireNonNull(destination);
        internal.dump(new WriteableUserPath(destination));

    }

    /**
     * Returns {@code true} if this recording uses the disk repository, {@code false} otherwise.
     * <p>
     * If no value is set, {@code true} is returned.
     *
     * @return {@code true} if the recording uses the disk repository, {@code false}
     *         otherwise
     */
    public boolean isToDisk() {
        return internal.isToDisk();
    }

    /**
     * Determines how much data is kept in the disk repository.
     * <p>
     * To control the amount of recording data that is stored on disk, the maximum
     * amount of data to retain can be specified. When the maximum limit is
     * exceeded, the Java Virtual Machine (JVM) removes the oldest chunk to make
     * room for a more recent chunk.
     * <p>
     * If neither maximum limit or the maximum age is set, the size of the
     * recording may grow indefinitely.
     *
     * @param maxSize the amount of data to retain, {@code 0} if infinite
     *
     * @throws IllegalArgumentException if <code>maxSize</code> is negative
     *
     * @throws IllegalStateException if the recording is in {@code CLOSED} state
     */
    public void setMaxSize(long maxSize) {
        if (maxSize < 0) {
            throw new IllegalArgumentException("Max size of recording can't be negative");
        }
        internal.setMaxSize(maxSize);
    }

        /**
         * Determines how often events are made available for streaming.
         *
         * @param interval the interval at which events are made available for streaming.
         *
         * @throws IllegalArgumentException if {@code interval} is negative
         *
         * @throws IllegalStateException if the recording is in the {@code CLOSED} state
         *
         * @since 14
         */
        public void setFlushInterval(Duration interval) {
            Objects.nonNull(interval);
            if (interval.isNegative()) {
                throw new IllegalArgumentException("Stream interval can't be negative");
            }
            internal.setFlushInterval(interval);
        }

    /**
     * Returns how often events are made available for streaming purposes.
     *
     * @return the flush interval, or {@code null} if no interval has been set
     *
     * @since 14
     */
    public Duration getFlushInterval() {
        return internal.getFlushInterval();
    }

    /**
     * Determines how far back data is kept in the disk repository.
     * <p>
     * To control the amount of recording data stored on disk, the maximum length of
     * time to retain the data can be specified. Data stored on disk that is older
     * than the specified length of time is removed by the Java Virtual Machine (JVM).
     * <p>
     * If neither maximum limit or the maximum age is set, the size of the
     * recording may grow indefinitely.
     *
     * @param maxAge the length of time that data is kept, or {@code null} if infinite
     *
     * @throws IllegalArgumentException if <code>maxAge</code> is negative
     *
     * @throws IllegalStateException if the recording is in the {@code CLOSED} state
     */
    public void setMaxAge(Duration maxAge) {
        if (maxAge != null && maxAge.isNegative()) {
            throw new IllegalArgumentException("Max age of recording can't be negative");
        }
        internal.setMaxAge(maxAge);
    }

    /**
     * Sets a location where data is written on recording stop, or
     * {@code null} if data is not to be dumped.
     * <p>
     * If a destination is set, this recording is automatically closed
     * after data is successfully copied to the destination path.
     * <p>
     * If a destination is <em>not</em> set, Flight Recorder retains the
     * recording data until this recording is closed. Use the {@link #dump(Path)} method to
     * manually write data to a file.
     *
     * @param destination the destination path, or {@code null} if recording should
     *        not be dumped at stop
     *
     * @throws IllegalStateException if recording is in the {@code STOPPED} or
     *         {@code CLOSED} state.
     *
     * @throws SecurityException if a security manager exists and the caller
     *         doesn't have {@code FilePermission} to read, write, and delete the
     *         {@code destination} file
     *
     * @throws IOException if the path is not writable
     */
    public void setDestination(Path destination) throws IOException {
        internal.setDestination(destination != null ? new WriteableUserPath(destination) : null);
    }

    /**
     * Returns the destination file, where recording data is written when the
     * recording stops, or {@code null} if no destination is set.
     *
     * @return the destination file, or {@code null} if not set.
     */
    public Path getDestination() {
        WriteableUserPath usp = internal.getDestination();
        if (usp == null) {
            return null;
        } else {
            return usp.getPotentiallyMaliciousOriginal();
        }
    }

    /**
     * Returns a unique ID for this recording.
     *
     * @return the recording ID
     */
    public long getId() {
        return internal.getId();
    }

    /**
     * Sets a human-readable name (for example, {@code "My Recording"}).
     *
     * @param name the recording name, not {@code null}
     *
     * @throws IllegalStateException if the recording is in {@code CLOSED} state
     */
    public void setName(String name) {
        Objects.requireNonNull(name);
        internal.setName(name);
    }

    /**
     * Sets whether this recording is dumped to disk when the JVM exits.
     *
     * @param dumpOnExit if this recording should be dumped when the JVM exits
     */
    public void setDumpOnExit(boolean dumpOnExit) {
        internal.setDumpOnExit(dumpOnExit);
    }

    /**
     * Returns whether this recording is dumped to disk when the JVM exits.
     * <p>
     * If dump on exit is not set, {@code false} is returned.
     *
     * @return {@code true} if the recording is dumped on exit, {@code false}
     *         otherwise.
     */
    public boolean getDumpOnExit() {
        return internal.getDumpOnExit();
    }

    /**
     * Determines whether this recording is continuously flushed to the disk
     * repository or data is constrained to what is available in memory buffers.
     *
     * @param disk {@code true} if this recording is written to disk,
     *        {@code false} if in-memory
     *
     */
    public void setToDisk(boolean disk) {
        internal.setToDisk(disk);
    }

    /**
     * Creates a data stream for a specified interval.
     * <p>
     * The stream may contain some data outside the specified range.
     *
     * @param the start start time for the stream, or {@code null} to get data from
     *        start time of the recording
     *
     * @param the end end time for the stream, or {@code null} to get data until the
     *        present time.
     *
     * @return an input stream, or {@code null} if no data is available in the
     *         interval.
     *
     * @throws IllegalArgumentException if {@code end} happens before
     *         {@code start}
     *
     * @throws IOException if a stream can't be opened
     */
    public InputStream getStream(Instant start, Instant end) throws IOException {
        if (start != null && end != null && end.isBefore(start)) {
            throw new IllegalArgumentException("End time of requested stream must not be before start time");
        }
        return internal.open(start, end);
    }

    /**
     * Returns the specified duration for this recording, or {@code null} if no
     * duration is set.
     * <p>
     * The duration can be set only when the recording is in the
     * {@link RecordingState#NEW} state.
     *
     * @return the desired duration of the recording, or {@code null} if no duration
     *         has been set.
     */
    public Duration getDuration() {
        return internal.getDuration();
    }

    /**
     * Sets a duration for how long a recording runs before it stops.
     * <p>
     * By default, a recording has no duration ({@code null}).
     *
     * @param duration the duration, or {@code null} if no duration is set
     *
     * @throws IllegalStateException if recording is in the {@code STOPPED} or {@code CLOSED} state
     */
    public void setDuration(Duration duration) {
        internal.setDuration(duration);
    }

    /**
     * Enables the event with the specified name.
     * <p>
     * If multiple events have the same name (for example, the same class is loaded
     * in different class loaders), then all events that match the name are enabled. To
     * enable a specific class, use the {@link #enable(Class)} method or a {@code String}
     * representation of the event type ID.
     *
     * @param name the settings for the event, not {@code null}
     *
     * @return an event setting for further configuration, not {@code null}
     *
     * @see EventType
     */
    public EventSettings enable(String name) {
        Objects.requireNonNull(name);
        RecordingSettings rs = new RecordingSettings(this, name);
        rs.with("enabled", "true");
        return rs;
    }

    /**
     * Disables event with the specified name.
     * <p>
     * If multiple events with same name (for example, the same class is loaded
     * in different class loaders), then all events that match the
     * name is disabled. To disable a specific class, use the
     * {@link #disable(Class)} method or a {@code String} representation of the event
     * type ID.
     *
     * @param name the settings for the event, not {@code null}
     *
     * @return an event setting for further configuration, not {@code null}
     *
     */
    public EventSettings disable(String name) {
        Objects.requireNonNull(name);
        RecordingSettings rs = new RecordingSettings(this, name);
        rs.with("enabled", "false");
        return rs;
    }

    /**
     * Enables event.
     *
     * @param eventClass the event to enable, not {@code null}
     *
     * @throws IllegalArgumentException if {@code eventClass} is an abstract
     *         class or not a subclass of {@link Event}
     *
     * @return an event setting for further configuration, not {@code null}
     */
    public EventSettings enable(Class<? extends Event> eventClass) {
        Objects.requireNonNull(eventClass);
        RecordingSettings rs = new RecordingSettings(this, eventClass);
        rs.with("enabled", "true");
        return rs;
    }

    /**
     * Disables event.
     *
     * @param eventClass the event to enable, not {@code null}
     *
     * @throws IllegalArgumentException if {@code eventClass} is an abstract
     *         class or not a subclass of {@link Event}
     *
     * @return an event setting for further configuration, not {@code null}
     *
     */
    public EventSettings disable(Class<? extends Event> eventClass) {
        Objects.requireNonNull(eventClass);
        RecordingSettings rs = new RecordingSettings(this, eventClass);
        rs.with("enabled", "false");
        return rs;
    }

    // package private
    PlatformRecording getInternal() {
        return internal;
    }

    private void setSetting(String id, String value) {
        Objects.requireNonNull(id);
        Objects.requireNonNull(value);
        internal.setSetting(id, value);
    }

}
