/*
 * Copyright (c) 2016, 2018, 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 jdk.jfr.internal.LogLevel.DEBUG;
import static jdk.jfr.internal.LogLevel.WARN;
import static jdk.jfr.internal.LogTag.JFR;

import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.FileChannel;
import java.nio.file.StandardOpenOption;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.TimerTask;
import java.util.TreeMap;

import jdk.jfr.Configuration;
import jdk.jfr.FlightRecorderListener;
import jdk.jfr.Recording;
import jdk.jfr.RecordingState;
import jdk.jfr.internal.SecuritySupport.SafePath;

public final class PlatformRecording implements AutoCloseable {

    private final PlatformRecorder recorder;
    private final long id;
    // Recording settings
    private Map<String, String> settings = new LinkedHashMap<>();
    private Duration duration;
    private Duration maxAge;
    private long maxSize;

    private WriteableUserPath destination;

    private boolean toDisk = true;
    private String name;
    private boolean dumpOnExit;
    private SafePath dumpOnExitDirectory = new SafePath(".");
    // Timestamp information
    private Instant stopTime;
    private Instant startTime;

    // Misc, information
    private RecordingState state = RecordingState.NEW;
    private long size;
    private final LinkedList<RepositoryChunk> chunks = new LinkedList<>();
    private volatile Recording recording;
    private TimerTask stopTask;
    private TimerTask startTask;
    private AccessControlContext noDestinationDumpOnExitAccessControlContext;
    private boolean shuoldWriteActiveRecordingEvent = true;

    PlatformRecording(PlatformRecorder recorder, long id) {
        // Typically the access control context is taken
        // when you call dump(Path) or setDdestination(Path),
        // but if no destination is set and dumponexit=true
        // the control context of the recording is taken when the
        // Recording object is constructed. This works well for
        // -XX:StartFlightRecording and JFR.dump
        this.noDestinationDumpOnExitAccessControlContext = AccessController.getContext();
        this.id = id;
        this.recorder = recorder;
        this.name = String.valueOf(id);
    }

    public void start() {
        RecordingState oldState;
        RecordingState newState;
        synchronized (recorder) {
            oldState = getState();
            if (!Utils.isBefore(state, RecordingState.RUNNING)) {
                throw new IllegalStateException("Recording can only be started once.");
            }
            if (startTask != null) {
                startTask.cancel();
                startTask = null;
                startTime = null;
            }
            recorder.start(this);
            Logger.log(LogTag.JFR, LogLevel.INFO, () -> {
                // Only print non-default values so it easy to see
                // which options were added
                StringJoiner options = new StringJoiner(", ");
                if (!toDisk) {
                    options.add("disk=false");
                }
                if (maxAge != null) {
                    options.add("maxage=" + Utils.formatTimespan(maxAge, ""));
                }
                if (maxSize != 0) {
                    options.add("maxsize=" + Utils.formatBytesCompact(maxSize));
                }
                if (dumpOnExit) {
                    options.add("dumponexit=true");
                }
                if (duration != null) {
                    options.add("duration=" + Utils.formatTimespan(duration, ""));
                }
                if (destination != null) {
                    options.add("filename=" + destination.getRealPathText());
                }
                String optionText = options.toString();
                if (optionText.length() != 0) {
                    optionText = "{" + optionText + "}";
                }
                return "Started recording \"" + getName() + "\" (" + getId() + ") " + optionText;
            });
            newState = getState();
        }
        notifyIfStateChanged(oldState, newState);
    }

    public boolean stop(String reason) {
        RecordingState oldState;
        RecordingState newState;
        synchronized (recorder) {
            oldState = getState();
            if (stopTask != null) {
                stopTask.cancel();
                stopTask = null;
            }
            recorder.stop(this);
            String endText = reason == null ? "" : ". Reason \"" + reason + "\".";
            Logger.log(LogTag.JFR, LogLevel.INFO, "Stopped recording \"" + getName() + "\" (" + getId() + ")" + endText);
            this.stopTime = Instant.now();
            newState = getState();
        }
        WriteableUserPath dest = getDestination();

        if (dest != null) {
            try {
                dumpStopped(dest);
                Logger.log(LogTag.JFR, LogLevel.INFO, "Wrote recording \"" + getName() + "\" (" + getId() + ") to " + dest.getRealPathText());
                notifyIfStateChanged(newState, oldState);
                close(); // remove if copied out
            } catch(IOException e) {
                // throw e; // BUG8925030
            }
        } else {
            notifyIfStateChanged(newState, oldState);
        }
        return true;
    }

    public void scheduleStart(Duration delay) {
        synchronized (recorder) {
            ensureOkForSchedule();

            startTime = Instant.now().plus(delay);
            LocalDateTime now = LocalDateTime.now().plus(delay);
            setState(RecordingState.DELAYED);
            startTask = createStartTask();
            recorder.getTimer().schedule(startTask, delay.toMillis());
            Logger.log(LogTag.JFR, LogLevel.INFO, "Scheduled recording \"" + getName() + "\" (" + getId() + ") to start at " + now);
        }
    }

    private void ensureOkForSchedule() {
        if (getState() != RecordingState.NEW) {
            throw new IllegalStateException("Only a new recoridng can be scheduled for start");
        }
    }

    private TimerTask createStartTask() {
        // Taking ref. to recording here.
        // Opens up for memory leaks.
        return new TimerTask() {
            @Override
            public void run() {
                synchronized (recorder) {
                    if (getState() != RecordingState.DELAYED) {
                        return;
                    }
                    start();
                }
            }
        };
    }

    void scheduleStart(Instant startTime) {
        synchronized (recorder) {
            ensureOkForSchedule();
            this.startTime = startTime;
            setState(RecordingState.DELAYED);
            startTask = createStartTask();
            recorder.getTimer().schedule(startTask, startTime.toEpochMilli());
        }
    }

    public Map<String, String> getSettings() {
        synchronized (recorder) {
            return settings;
        }
    }

    public long getSize() {
        return size;
    }

    public Instant getStopTime() {
        synchronized (recorder) {
            return stopTime;
        }
    }

    public Instant getStartTime() {
        synchronized (recorder) {
            return startTime;
        }
    }

    public Long getMaxSize() {
        synchronized (recorder) {
            return maxSize;
        }
    }

    public Duration getMaxAge() {
        synchronized (recorder) {
            return maxAge;
        }
    }

    public String getName() {
        synchronized (recorder) {
            return name;
        }
    }

    public RecordingState getState() {
        synchronized (recorder) {
            return state;
        }
    }

    @Override
    public void close() {
        RecordingState oldState;
        RecordingState newState;

        synchronized (recorder) {
            oldState = getState();
            if (RecordingState.CLOSED != getState()) {
                if (startTask != null) {
                    startTask.cancel();
                    startTask = null;
                }
                recorder.finish(this);
                for (RepositoryChunk c : chunks) {
                    removed(c);
                }
                chunks.clear();
                setState(RecordingState.CLOSED);
                Logger.log(LogTag.JFR, LogLevel.INFO, "Closed recording \"" + getName() + "\" (" + getId() + ")");
            }
            newState = getState();
        }
        notifyIfStateChanged(newState, oldState);
    }

    // To be used internally when doing dumps.
    // Caller must have recorder lock and close recording before releasing lock
    public PlatformRecording newSnapshotClone(String reason, Boolean pathToGcRoots) throws IOException {
        if(!Thread.holdsLock(recorder)) {
            throw new InternalError("Caller must have recorder lock");
        }
        RecordingState state = getState();
        if (state == RecordingState.CLOSED) {
            throw new IOException("Recording \"" + name + "\" (id=" + id + ") has been closed, no contents to write");
        }
        if (state == RecordingState.DELAYED || state == RecordingState.NEW) {
            throw new IOException("Recording \"" + name + "\" (id=" + id + ") has not started, no contents to write");
        }
        if (state == RecordingState.STOPPED) {
            PlatformRecording clone = recorder.newTemporaryRecording();
            for (RepositoryChunk r : chunks) {
                clone.add(r);
            }
            return clone;
        }

        // Recording is RUNNING, create a clone
        PlatformRecording clone = recorder.newTemporaryRecording();
        clone.setShouldWriteActiveRecordingEvent(false);
        clone.setName(getName());
        clone.setToDisk(true);
        // We purposely don't clone settings here, since
        // a union a == a
        if (!isToDisk()) {
            // force memory contents to disk
            clone.start();
        } else {
            // using existing chunks on disk
            for (RepositoryChunk c : chunks) {
                clone.add(c);
            }
            clone.setState(RecordingState.RUNNING);
            clone.setStartTime(getStartTime());
        }
        if (pathToGcRoots == null) {
            clone.setSettings(getSettings()); // needed for old object sample
            clone.stop(reason); // dumps to destination path here
        } else {
            // Risk of violating lock order here, since
            // clone.stop() will take recorder lock inside
            // metadata lock, but OK if we already
            // have recorder lock when we entered metadata lock
            synchronized (MetadataRepository.getInstance()) {
                clone.setSettings(OldObjectSample.createSettingsForSnapshot(this, pathToGcRoots));
                clone.stop(reason);
            }
        }
        return clone;
    }

    public boolean isToDisk() {
        synchronized (recorder) {
            return toDisk;
        }
    }

    public void setMaxSize(long maxSize) {
        synchronized (recorder) {
            if (getState() == RecordingState.CLOSED) {
                throw new IllegalStateException("Can't set max age when recording is closed");
            }
            this.maxSize = maxSize;
            trimToSize();
        }
    }

    public void setDestination(WriteableUserPath userSuppliedPath) throws IOException {
        synchronized (recorder) {
            checkSetDestination(userSuppliedPath);
            this.destination = userSuppliedPath;
        }
    }

    public void checkSetDestination(WriteableUserPath userSuppliedPath) throws IOException {
        synchronized (recorder) {
            if (Utils.isState(getState(), RecordingState.STOPPED, RecordingState.CLOSED)) {
                throw new IllegalStateException("Destination can't be set on a recording that has been stopped/closed");
            }
        }
    }

    public WriteableUserPath getDestination() {
        synchronized (recorder) {
            return destination;
        }
    }

    void setState(RecordingState state) {
        synchronized (recorder) {
            this.state = state;
        }
    }

    void setStartTime(Instant startTime) {
        synchronized (recorder) {
            this.startTime = startTime;
        }
    }

    void setStopTime(Instant timeStamp) {
        synchronized (recorder) {
            stopTime = timeStamp;
        }
    }

    public long getId() {
        synchronized (recorder) {
            return id;
        }
    }

    public void setName(String name) {
        synchronized (recorder) {
            ensureNotClosed();
            this.name = name;
        }
    }

    private void ensureNotClosed() {
        if (getState() == RecordingState.CLOSED) {
            throw new IllegalStateException("Can't change name on a closed recording");
        }
    }

    public void setDumpOnExit(boolean dumpOnExit) {
        synchronized (recorder) {
            this.dumpOnExit = dumpOnExit;
        }
    }

    public boolean getDumpOnExit() {
        synchronized (recorder) {
            return dumpOnExit;
        }
    }

    public void setToDisk(boolean toDisk) {
        synchronized (recorder) {
            if (Utils.isState(getState(), RecordingState.NEW, RecordingState.DELAYED)) {
                this.toDisk = toDisk;
            } else {
                throw new IllegalStateException("Recording option disk can't be changed after recording has started");
            }
        }
    }

    public void setSetting(String id, String value) {
        synchronized (recorder) {
            this.settings.put(id, value);
            if (getState() == RecordingState.RUNNING) {
                recorder.updateSettings();
            }
        }
    }

    public void setSettings(Map<String, String> settings) {
        setSettings(settings, true);
    }

    private void setSettings(Map<String, String> settings, boolean update) {
        if (Logger.shouldLog(LogTag.JFR_SETTING, LogLevel.INFO) && update) {
            TreeMap<String, String> ordered = new TreeMap<>(settings);
            Logger.log(LogTag.JFR_SETTING, LogLevel.INFO, "New settings for recording \"" + getName() + "\" (" + getId() + ")");
            for (Map.Entry<String, String> entry : ordered.entrySet()) {
                String text = entry.getKey() + "=\"" + entry.getValue() + "\"";
                Logger.log(LogTag.JFR_SETTING, LogLevel.INFO, text);
            }
        }
        synchronized (recorder) {
            this.settings = new LinkedHashMap<>(settings);
            if (getState() == RecordingState.RUNNING && update) {
                recorder.updateSettings();
            }
        }
    }

    private void notifyIfStateChanged(RecordingState newState, RecordingState oldState) {
        if (oldState == newState) {
            return;
        }
        for (FlightRecorderListener cl : PlatformRecorder.getListeners()) {
            try {
                cl.recordingStateChanged(getRecording());
            } catch (RuntimeException re) {
                Logger.log(JFR, WARN, "Error notifying recorder listener:" + re.getMessage());
            }
        }
    }

    public void setRecording(Recording recording) {
        this.recording = recording;
    }

    public Recording getRecording() {
        return recording;
    }

    @Override
    public String toString() {
        return getName() + " (id=" + getId() + ") " + getState();
    }

    public void setConfiguration(Configuration c) {
        setSettings(c.getSettings());
    }

    public void setMaxAge(Duration maxAge) {
        synchronized (recorder) {
            if (getState() == RecordingState.CLOSED) {
                throw new IllegalStateException("Can't set max age when recording is closed");
            }
            this.maxAge = maxAge;
            if (maxAge != null) {
                trimToAge(Instant.now().minus(maxAge));
            }
        }
    }

    void appendChunk(RepositoryChunk chunk) {
        if (!chunk.isFinished()) {
            throw new Error("not finished chunk " + chunk.getStartTime());
        }
        synchronized (recorder) {
            if (!toDisk) {
                return;
            }
            if (maxAge != null) {
                trimToAge(chunk.getEndTime().minus(maxAge));
            }
            chunks.addLast(chunk);
            added(chunk);
            trimToSize();
        }
    }

    private void trimToSize() {
        if (maxSize == 0) {
            return;
        }
        while (size > maxSize && chunks.size() > 1) {
            RepositoryChunk c = chunks.removeFirst();
            removed(c);
        }
    }

    private void trimToAge(Instant oldest) {
        while (!chunks.isEmpty()) {
            RepositoryChunk oldestChunk = chunks.peek();
            if (oldestChunk.getEndTime().isAfter(oldest)) {
                return;
            }
            chunks.removeFirst();
            removed(oldestChunk);
        }
    }

    void add(RepositoryChunk c) {
        chunks.add(c);
        added(c);
    }

    private void added(RepositoryChunk c) {
        c.use();
        size += c.getSize();
        Logger.log(JFR, DEBUG, () -> "Recording \"" + name + "\" (" + id + ") added chunk " + c.toString() + ", current size=" + size);
    }

    private void removed(RepositoryChunk c) {
        size -= c.getSize();
        Logger.log(JFR, DEBUG, () -> "Recording \"" + name + "\" (" + id + ") removed chunk " + c.toString() + ", current size=" + size);
        c.release();
    }

    public List<RepositoryChunk> getChunks() {
        return chunks;
    }

    public InputStream open(Instant start, Instant end) throws IOException {
        synchronized (recorder) {
            if (getState() != RecordingState.STOPPED) {
                throw new IOException("Recording must be stopped before it can be read.");
            }
            List<RepositoryChunk> chunksToUse = new ArrayList<RepositoryChunk>();
            for (RepositoryChunk chunk : chunks) {
                if (chunk.isFinished()) {
                    Instant chunkStart = chunk.getStartTime();
                    Instant chunkEnd = chunk.getEndTime();
                    if (start == null || !chunkEnd.isBefore(start)) {
                        if (end == null || !chunkStart.isAfter(end)) {
                            chunksToUse.add(chunk);
                        }
                    }
                }
            }
            if (chunksToUse.isEmpty()) {
                return null;
            }
            return new ChunkInputStream(chunksToUse);
        }
    }

    public Duration getDuration() {
        synchronized (recorder) {
            return duration;
        }
    }

    void setInternalDuration(Duration duration) {
        this.duration = duration;
    }

    public void setDuration(Duration duration) {
        synchronized (recorder) {
            if (Utils.isState(getState(), RecordingState.STOPPED, RecordingState.CLOSED)) {
                throw new IllegalStateException("Duration can't be set after a recording has been stopped/closed");
            }
            setInternalDuration(duration);
            if (getState() != RecordingState.NEW) {
                updateTimer();
            }
        }
    }

    void updateTimer() {
        if (stopTask != null) {
            stopTask.cancel();
            stopTask = null;
        }
        if (getState() == RecordingState.CLOSED) {
            return;
        }
        if (duration != null) {
            stopTask = createStopTask();
            recorder.getTimer().schedule(stopTask, new Date(startTime.plus(duration).toEpochMilli()));
        }
    }

    TimerTask createStopTask() {
        return new TimerTask() {
            @Override
            public void run() {
                try {
                    stop("End of duration reached");
                } catch (Throwable t) {
                    // Prevent malicious user to propagate exception callback in the wrong context
                    Logger.log(LogTag.JFR, LogLevel.ERROR, "Could not stop recording.");
                }
            }
        };
    }

    public Recording newCopy(boolean stop) {
        return recorder.newCopy(this, stop);
    }

    void setStopTask(TimerTask stopTask) {
        synchronized (recorder) {
            this.stopTask = stopTask;
        }
    }

    void clearDestination() {
        destination = null;
    }

    public AccessControlContext getNoDestinationDumpOnExitAccessControlContext() {
        return noDestinationDumpOnExitAccessControlContext;
    }

    void setShouldWriteActiveRecordingEvent(boolean shouldWrite) {
        this.shuoldWriteActiveRecordingEvent = shouldWrite;
    }

    boolean shouldWriteMetadataEvent() {
        return shuoldWriteActiveRecordingEvent;
    }

    // Dump running and stopped recordings
    public void dump(WriteableUserPath writeableUserPath) throws IOException {
        synchronized (recorder) {
            try(PlatformRecording p = newSnapshotClone("Dumped by user", null))  {
                p.dumpStopped(writeableUserPath);
            }
        }
    }

    public void dumpStopped(WriteableUserPath userPath) throws IOException {
        synchronized (recorder) {
                userPath.doPriviligedIO(() -> {
                    try (ChunksChannel cc = new ChunksChannel(chunks); FileChannel fc = FileChannel.open(userPath.getReal(), StandardOpenOption.WRITE, StandardOpenOption.APPEND)) {
                        cc.transferTo(fc);
                        fc.force(true);
                    }
                    return null;
                });
        }
    }

    public void filter(Instant begin, Instant end, Long maxSize) {
        synchronized (recorder) {
            List<RepositoryChunk> result = removeAfter(end, removeBefore(begin, new ArrayList<>(chunks)));
            if (maxSize != null) {
                if (begin != null && end == null) {
                    result = reduceFromBeginning(maxSize, result);
                } else {
                    result = reduceFromEnd(maxSize, result);
                }
            }
            int size = 0;
            for (RepositoryChunk r : result) {
                size += r.getSize();
                r.use();
            }
            this.size = size;
            for (RepositoryChunk r : chunks) {
                r.release();
            }
            chunks.clear();
            chunks.addAll(result);
        }
    }

    private static List<RepositoryChunk> removeBefore(Instant time, List<RepositoryChunk> input) {
        if (time == null) {
            return input;
        }
        List<RepositoryChunk> result = new ArrayList<>(input.size());
        for (RepositoryChunk r : input) {
            if (!r.getEndTime().isBefore(time)) {
                result.add(r);
            }
        }
        return result;
    }

    private static List<RepositoryChunk> removeAfter(Instant time, List<RepositoryChunk> input) {
        if (time == null) {
            return input;
        }
        List<RepositoryChunk> result = new ArrayList<>(input.size());
        for (RepositoryChunk r : input) {
            if (!r.getStartTime().isAfter(time)) {
                result.add(r);
            }
        }
        return result;
    }

    private static List<RepositoryChunk> reduceFromBeginning(Long maxSize, List<RepositoryChunk> input) {
        if (maxSize == null || input.isEmpty()) {
            return input;
        }
        List<RepositoryChunk> result = new ArrayList<>(input.size());
        long total = 0;
        for (RepositoryChunk r : input) {
            total += r.getSize();
            if (total > maxSize) {
                break;
            }
            result.add(r);
        }
        // always keep at least one chunk
        if (result.isEmpty()) {
            result.add(input.get(0));
        }
        return result;
    }

    private static List<RepositoryChunk> reduceFromEnd(Long maxSize, List<RepositoryChunk> input) {
        Collections.reverse(input);
        List<RepositoryChunk> result = reduceFromBeginning(maxSize, input);
        Collections.reverse(result);
        return result;
    }

    public void setDumpOnExitDirectory(SafePath directory) {
       this.dumpOnExitDirectory = directory;
    }

    public SafePath getDumpOnExitDirectory()  {
        return this.dumpOnExitDirectory;
    }
}
