package ctbrec.recorder;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.stream.Collectors;

import ctbrec.Model;
import ctbrec.Recording;
import ctbrec.io.HttpClient;

public interface Recorder {
    public void startRecording(Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException, IllegalStateException;

    public void stopRecording(Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException, IllegalStateException;

    public void switchStreamSource(Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException, IllegalStateException;

    /**
     * Returns true, if a model is in the list of models to record. This does not reflect, if there currently is a recording running. The model might be offline
     * aswell.
     */
    public boolean isTracked(Model model);

    /**
     * Get the list of all models, which are tracked by ctbrec
     *
     * @return a List of Model objects, which might be empty
     */
    public List<Model> getModels();

    public List<Recording> getRecordings() throws IOException, InvalidKeyException, NoSuchAlgorithmException, IllegalStateException;

    public void delete(Recording recording) throws IOException, InvalidKeyException, NoSuchAlgorithmException, IllegalStateException;

    public void shutdown();

    public void suspendRecording(Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException, IllegalStateException;
    public void resumeRecording(Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException, IllegalStateException;

    public boolean isSuspended(Model model);

    /**
     * Returns only the models from getModels(), which are online
     * @return
     */
    public List<Model> getOnlineModels();

    /**
     * Returns only the models from getModels(), which are actually recorded right now
     * @return
     * @throws IOException
     * @throws IllegalStateException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     */
    public default List<Model> getCurrentlyRecording() throws InvalidKeyException, NoSuchAlgorithmException, IllegalStateException, IOException {
        List<Recording> recordings = getRecordings();
        return getModels().stream().filter(m -> {
            for (Recording recording : recordings) {
                if (recording.getStatus() == Recording.State.RECORDING && recording.getModelName().equals(m.getSanitizedNamed())) {
                    return true;
                }
            }
            return false;
        }).collect(Collectors.toList());
    }

    public HttpClient getHttpClient();

    /**
     * Get the total size of the filesystem we are recording to
     * @return the total size in bytes
     * @throws IOException
     */
    public long getTotalSpaceBytes() throws IOException;

    /**
     * Get the free space left on the filesystem we are recording to
     * @return the free space in bytes
     * @throws IOException
     */
    public long getFreeSpaceBytes() throws IOException;

    /**
     * Regenerate the playlist for a recording. This is helpful, if the
     * playlist is corrupt or hasn't been generated for whatever reason
     * @param recording
     * @throws IllegalStateException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     * @throws IOException
     */
    public void regeneratePlaylist(Recording recording) throws IOException, InvalidKeyException, NoSuchAlgorithmException, IllegalStateException;

}
