using System.Collections.Generic;
using System.IO;
using BizHawk.Common;
using BizHawk.Emulation.Common;
namespace BizHawk.Client.Common
{
// TODO: message callback / event handler
// TODO: consider other event handlers, switching modes?
public interface IMovie
{
#region Status
bool IsCountingRerecords { get; set; }
bool IsActive { get; }
bool IsPlaying { get; }
bool IsRecording { get; }
bool IsFinished { get; }
bool Changes { get; }
#endregion
#region Properties
///
/// Gets the total number of frames that count towards the completion time of the movie
/// Possibly (but unlikely different from InputLogLength (could be infinity, or maybe an implementation automatically discounts empty frames at the end of a movie, etc)
///
double FrameCount { get; }
///
/// Gets the actual length of the input log, should only be used by code that iterates or needs a real length
///
int InputLogLength { get; }
///
/// Returns the file extension for this implementation
///
string PreferredExtension { get; }
///
/// Sync Settings from the Core
///
string SyncSettingsJson { get; set; }
SubtitleList Subtitles { get; }
IList Comments { get; }
// savestate anchor.
string TextSavestate { get; set; }
byte[] BinarySavestate { get; set; }
int[] SavestateFramebuffer { get; set; }
// saveram anchor
byte[] SaveRam { get; set; }
ulong Rerecords { get; set; }
bool StartsFromSavestate { get; set; }
bool StartsFromSaveRam { get; set; }
string GameName { get; set; }
string SystemID { get; set; }
string Hash { get; set; }
string Author { get; set; }
string Core { get; set; }
string EmulatorVersion { get; set; }
string FirmwareHash { get; set; }
string BoardName { get; set; }
///
/// Loads from the HawkFile the minimal amount of information needed to determine Header info and Movie length
/// This method is intended to be more performant than a full load
///
bool PreLoadHeaderAndLength(HawkFile hawkFile);
///
/// Returns header key value pairs stored in the movie file
///
IDictionary HeaderEntries { get; }
///
/// Forces the creation of a backup file of the current movie state
///
void SaveBackup();
///
/// Creates an instance of the Input log entry used to generate the input log
///
ILogEntryGenerator LogGeneratorInstance();
#endregion
#region File Handling API
// Filename of the movie, settable by the client
string Filename { get; set; }
///
/// Tells the movie to load the contents of Filename
///
/// Return whether or not the file was successfully loaded
bool Load(bool preload);
///
/// Instructs the movie to save the current contents to Filename
///
void Save();
///
/// Extracts the current input log from the user.
/// This is provided as the means for putting the input log into savestates,
/// for the purpose of out of order savestate loading (known as "bullet-proof rerecording")
///
/// returns a string represntation of the input log in its current state
string GetInputLog();
///
/// Writes the input log directly to the stream, bypassing the need to load it all into ram as a string
///
void WriteInputLog(TextWriter writer);
///
/// Gets one frame from the input log.
///
/// The frame to get.
///
string GetInputLogEntry(int frame);
///
/// Compares the input log inside reader with the movie's current input to see if the reader's input belongs to the same timeline,
/// in other words, if reader's input is completely contained in the movie's input, then it is considered in the same timeline
///
/// The reader containing the contents of the input log
/// Returns an error message, if any
/// Returns whether or not the input log in reader is in the same timeline as the movie
bool CheckTimeLines(TextReader reader, out string errorMessage);
///
/// Takes reader and extracts the input log, then replaces the movies input log with it
///
/// The reader containing the contents of the input log
/// Returns an error message, if any
///
bool ExtractInputLog(TextReader reader, out string errorMessage);
#endregion
#region Mode Handling API
///
/// Tells the movie to start recording from the beginning.
///
void StartNewRecording();
///
/// Tells the movie to start playback from the beginning
///
void StartNewPlayback();
///
/// Sets the movie to inactive (note that it will still be in memory)
/// The saveChanges flag will tell the movie to save its contents to disk
///
/// if true, will save to disk
/// Whether or not the movie was saved
bool Stop(bool saveChanges = true);
///
/// Switches to record mode
///
void SwitchToRecord();
///
/// Switches to playback mode
///
void SwitchToPlay();
///
/// Tells the movie to go into "Finished" mode, where the user resumes control of input but the movie is still loaded in memory
///
void FinishedMode();
#endregion
#region Editing API
///
/// Replaces the given frame's input with an empty frame
///
void ClearFrame(int frame);
///
/// Adds the given input to the movie
/// Note: this edits the input log without the normal movie recording logic applied
///
void AppendFrame(IController source);
///
/// Replaces the input at the given frame with the given input
/// Note: this edits the input log without the normal movie recording logic applied
///
void PokeFrame(int frame, IController source);
///
/// Records the given input into the given frame,
/// This is subject to normal movie recording logic
///
void RecordFrame(int frame, IController source);
///
/// Instructs the movie to remove all input from its input log after frame,
/// AFter truncating, frame will be the last frame of input in the movie's input log
///
/// The frame at which to truncate
void Truncate(int frame);
///
/// Gets a single frame of input via a controller state
///
/// The frame of input to be retrieved
/// A controller state representing the specified frame of input, if frame is out of range, will return null
IController GetInputState(int frame);
#endregion
}
}