/////////////////////////////////////////////////////////////////////////////
// Name:        DVD.h
// Purpose:     The class to store a DVD Structure (Titles/Menus)
// Author:      Alex Thuering
// Created:	29.01.2003
// RCS-ID:      $Id: DVD.h,v 1.26 2008/03/02 18:54:59 ntalex Exp $
// Copyright:   (c) Alex Thuering
// Licence:     GPL
/////////////////////////////////////////////////////////////////////////////

#ifndef DVDAUTHOR_H
#define DVDAUTHOR_H

#include <wx/wx.h>
#include <wx/image.h>
#include <wx/dynarray.h>
#include "Menu.h"
#include "Slideshow.h"

class wxSvgXmlNode;
class DVD;

class TextSub
{
  public:
    TextSub(wxString filename = wxT(""));
    
    wxString GetFilename() { return m_filename; }
    void SetFilename(wxString value) { m_filename = value; }
    
    wxString GetCharacterSet() { return m_characterSet; }
    void SetCharacterSet(wxString value) { m_characterSet= value; }
    
    wxString GetFont() { return m_font; }
    void Set(wxString value) { m_font = value; }
    
    double GetFontSize() { return m_fontSize; }
    void SetFontSize(double value) { m_fontSize = value; }
    
    wxString GetHAlignment() { return m_hAlignment; }
    void SetHAlignment(wxString value) { m_hAlignment = value; }
    
    wxString GetVAlignment() { return m_vAlignment; }
    void SetVAlignment(wxString value) { m_vAlignment = value; }
    
    int GetLeftMargin() { return m_leftMargin; }
    void SetLeftMargin(int value) { m_leftMargin = value; }
    
    int GetRightMargin() { return m_rightMargin; }
    void SetRightMargin(int value) { m_rightMargin = value; }
    
    int GetTopMargin() { return m_topMargin; }
    void SetTopMargin(int value) { m_topMargin = value; }
    
    int GetmBottomMargin() { return m_bottomMargin; }
    void SetBottomMargin(int value) { m_bottomMargin = value; }
    
    double GetSubtitleFps() { return m_subtitleFps; }
    void SetSubtitleFps(double value) { m_subtitleFps = value; }
    
    double GetMovieFps() { return m_movieFps; }
    void SetMovieFps(double value) { m_movieFps = value; }
    
    int GetMovieWidth() { return m_movieWidth; }
    void SetMovieWidth(int value) { m_movieWidth = value; }
    
    int GetMovieHeight() { return m_movieHeight; }
    void SetMovieHeight(int value) { m_movieHeight = value; }
    
    wxSvgXmlNode* GetXML(DVDFileType type);
	bool PutXML(wxSvgXmlNode* node);
    
    /** saves a configuration for spumux */
	bool SaveSpumux(wxString filename);
    
  protected:
    wxString m_filename;
    wxString m_characterSet; 
    wxString m_font;
    double m_fontSize;
    wxString m_hAlignment;
    wxString m_vAlignment;
    int m_leftMargin;
    int m_rightMargin;
    int m_topMargin;
    int m_bottomMargin;
    double m_subtitleFps;
    double m_movieFps;
    int m_movieWidth;
    int m_movieHeight;
};

WX_DEFINE_ARRAY(TextSub*, TextSubArray);
	
class Vob
{
  public:
    Vob(): m_pause(0), m_menu(NULL), m_slideshow(NULL) {}
    Vob(wxString filename): m_filename(filename), m_pause(0), m_menu(NULL), m_slideshow(NULL) {}
	Vob(Menu* menu): m_pause(0), m_menu(menu), m_slideshow(NULL) {}
    Vob(Slideshow* slideshow): m_pause(0), m_menu(NULL), m_slideshow(slideshow) {}
	~Vob();
	
    /** sets name of mpeg file for this vob*/
	void SetFilename(wxString value) { m_filename = value; UpdateInfo(); }
    /** returns name of mpeg file */
	wxString GetFilename() { return m_filename; }
	
    /** sets name of video file for this vob */
	void SetVideoFilename(wxString value) { m_videoFilename = value; UpdateInfo(); }
    /** returns name of video file */
	wxString GetVideoFilename() { return m_videoFilename; }
	
    /** returns array with audio tracks */
	wxArrayString& GetAudioFilenames() { return m_audioFilenames; }
    /** returns array with subtitle tracks */
    TextSubArray& GetSubtitles() { return m_subtitles; }
	
    /** sets file name of tempory vob file */
	void SetTmpFilename(wxString value) { m_tmpFilename = value; }
    /** returns file name of tempory vob file */
	wxString GetTmpFilename() { return m_tmpFilename; }
	
    /** sets chapter list */
	void SetChapters(wxString value) { m_chapters = value; }
    /** returns chapter list */
	wxString GetChapters() { return m_chapters; }
	/** returns the time of given chapter */
	long GetChapterTime(int chapter);
	
    /** sets pause */
	void SetPause(int value) { m_pause = value; }
    /** returns pause */
	int GetPause() { return m_pause; }

	void SetMenu(Menu* menu) { m_menu = menu; }	
	Menu* GetMenu() { return m_menu; }
    
    void SetSlideshow(Slideshow* slideshow) { m_slideshow = slideshow; }	
	Slideshow* GetSlideshow() { return m_slideshow; }
	
	/** returns duration of video in ms */
	inline double GetDuration() { return m_duration; }
	/** return video size */
	inline wxSize GetVideoSize() { return m_videoSize; }
	/** returns URI of video frame */
	wxString GetVideoFrameUri(int chapter, long position = -1);
	
	wxSvgXmlNode* GetXML(DVDFileType type, DVD* dvd);
	bool PutXML(wxSvgXmlNode* node);
	
	/** returns size im Kb
      * @param generated true if vob file already generated (before runnig of dvdauthor)
      */
	int GetSize(bool generated = false);
	
	static Vob* CreateEmptyVob(VideoFormat videoFormat, AudioFormat audioFormat);
	
  protected:
	wxString m_filename;
	wxString m_videoFilename;
	wxArrayString m_audioFilenames;
    TextSubArray m_subtitles;
	wxString m_tmpFilename;
	wxString m_chapters;
	int m_pause;
	Menu* m_menu;
    Slideshow* m_slideshow;
	static unsigned int GetFileSize(wxString filename);
	
	double m_duration;
	wxSize m_videoSize;
	void UpdateInfo();
};

WX_DEFINE_ARRAY(Vob*, VobArray);

class Pgc
{
  public:
	Pgc() { }
	~Pgc() { WX_CLEAR_ARRAY(m_vobs) }
	
	void SetEntry(wxString value) { m_entry = value; }
	wxString GetEntry() { return m_entry; }
	
	void SetPreCommands(wxString value) { m_pre = value; }
	wxString GetPreCommands() { return m_pre; }
	void SetPostCommands(wxString value) { m_post = value; }
	wxString GetPostCommands() { return m_post; }
	void SetPalette(wxString value) { m_palette = value; }
	wxString GetPalette() { return m_palette; }
	
	VobArray& GetVobs() { return m_vobs; }
	
	Menu* GetMenu();
    Slideshow* GetSlideshow();
	
	wxSvgXmlNode*	GetXML(DVDFileType type, DVD* dvd, wxString nextTitle);
	bool		PutXML(wxSvgXmlNode* node);
	
  protected:
	VobArray m_vobs;
	wxString m_entry, m_pre, m_post, m_palette;
};

WX_DEFINE_ARRAY(Pgc*, PgcArrayBase);

class Audio
{
  public:
	Audio() { m_channels = -1; }
	
	void SetFormat(wxString value) { m_format = value; }
	wxString GetFormat() { return m_format; }
	wxArrayString GetFormatStrings(wxString def);
	
	void SetChannels(int value) { m_channels = value; }
	int GetChannels() { return m_channels; }
	
	void SetQuant(wxString value) { m_quant = value; }
	wxString GetQuant() { return m_quant; }
	wxArrayString GetQuantStrings(wxString def);
	
	void SetDolby(wxString value) { m_dolby = value; }
	wxString GetDolby() { return m_dolby; }
	wxArrayString GetDolbyStrings(wxString def);
	
	void SetSamplerate(wxString value) { m_samplerate = value; }
	wxString GetSamplerate() { return m_samplerate; }
	wxArrayString GetSamplerateStrings(wxString def);
	
	void SetLang(wxString value) { m_lang = value; }
	wxString GetLang() { return m_lang; }
	
	wxSvgXmlNode*	GetXML(DVDFileType type);
	bool		PutXML(wxSvgXmlNode* node);
	
  protected:
	wxString m_format;
	int m_channels;
	wxString m_quant;
	wxString m_dolby;
	wxString m_samplerate;
	wxString m_lang;
};

class Video
{
  public:
	void SetFormat(wxString value) { m_format = value; }
	wxString GetFormat() { return m_format; }
	wxArrayString GetFormatStrings(wxString def);
	
	void SetAspect(wxString value) { m_aspect = value; }
	wxString GetAspect() { return m_aspect; }
	wxArrayString GetAspectStrings(wxString def);
	
	void SetResolution(wxString value) { m_resolution = value; }
	wxString GetResolution() { return m_resolution; }
	
	void SetCaption(wxString value) { m_caption = value; }
	wxString GetCaption() { return m_caption; }
	
	void SetWidescreen(wxString value) { m_widescreen = value; }
	wxString GetWidescreen() { return m_widescreen; }
	wxArrayString GetWidescreenStrings(wxString def);
	
	wxSvgXmlNode*	GetXML(DVDFileType type);
	bool		PutXML(wxSvgXmlNode* node);
	
  protected:
	wxString m_format;
	wxString m_aspect;
	wxString m_resolution;
	wxString m_caption;
	wxString m_widescreen;
};

class PgcArray: public PgcArrayBase
{
  public:
	Audio& GetAudio() { return m_audio; }
	Video& GetVideo() { return m_video; }
  
  protected:
	Audio m_audio;
	Video m_video;
};

class Menus: public PgcArray
{
  public:
	wxSvgXmlNode*	GetXML(DVDFileType type, DVD* dvd);
	bool		PutXML(wxSvgXmlNode* node);
};

class Titles: public PgcArray
{
  public:
	wxSvgXmlNode* GetXML(DVDFileType type, DVD* dvd, int nextTitleset);
	bool	   PutXML(wxSvgXmlNode* node);
};

class Titleset
{
  public:
	Titleset() { WX_CLEAR_ARRAY(m_menus); WX_CLEAR_ARRAY(m_titles); }
	
	Menus& GetMenus() { return m_menus; }
	Titles& GetTitles() { return m_titles; }
	
	inline bool IsEmpty() { return GetMenus().Count() == 0 && GetTitles().Count() == 0; }
	
	wxSvgXmlNode* GetXML(DVDFileType type, DVD* dvd, int nextTitleset = -1);
	bool PutXML(wxSvgXmlNode* node);
	
  protected:
	Menus m_menus;
	Titles m_titles;
};

class Vmgm: public Menus
{
  public:
	/** Returns the fpc (First Program Chain) commands */
    wxString GetFpc() { return m_fpc; }
    /** Sets the FPC (First Program Chain) commands */
    void SetFpc(wxString fpc) { m_fpc = fpc; }
    
    wxSvgXmlNode* GetXML(DVDFileType type, DVD* dvd);
	bool PutXML(wxSvgXmlNode* node);
  
  protected:
	wxString m_fpc;
};

WX_DEFINE_ARRAY(Titleset*, TitlesetArray);

class DVD
{
  public:
    DVD();
    ~DVD();
    
    /** returns volume name */
    wxString GetName() { return m_name; }
    /** sets volume name */
    void SetName(wxString name) { m_name = name; }
    
	/** returns true if creation of jumppads enabled */
	bool IsJumppadsEnabled() { return m_jumppad; }
	/** enables creation of jumppads */
	void EnableJumppads(bool enable = true) { m_jumppad = enable; }
	
	/** returns true if creation of empty menu enabled */
	bool IsEmptyMenuEnabled() { return m_emptyMenu; }
	/** enables creation of empty menu */
	void EnableEmptyMenu(bool enable = true) { m_emptyMenu = enable; }
	
	/** returns titlesets */
	TitlesetArray& GetTitlesets() { return m_titlesets; }
	/** returns vmgm menus */
	Vmgm& GetVmgm() { return m_vmgm; }
	
	/** returns index of new titleset (tsi) */
	int AddTitleset();
	/** returns index of new pgc */
	int AddMenu(VideoFormat format, int tsi = -1);
	/** returns index of new pgc */
	int AddPgc(int tsi, bool menu, Pgc* pgc = NULL);
	/** returns pgcs */
	PgcArray& GetPgcArray(int tsi, bool menus);
	/** returns vob from given titleset, pgc */
	Vob* GetVob(int tsi, bool isMenu, int pgci, int vobi);
	/** returns vob with menu from given titleset and pgc */
	Vob* GetMenuVob(int tsi, int pgci);
	/** returns menu from titleset tsi und pgc pgci */
	Menu* GetMenu(int tsi, int pgci);
	
	/** returns id for specified vob */
	static inline int MakeId(int tsi, int pgci, int vobi, bool menu)
	{ return ((tsi+1)<<24) + ((pgci*2+(menu ? 0 : 1))<<8) + vobi; }
	static inline int GetTsi(int id)  { return (id>>24)-1; }
	static inline int GetPgci(int id) { return ((id>>8) & 0xFFFF) / 2; }
	static inline bool IsMenu(int id) { return !(((id>>8) & 0xFFFF) % 2); }
	static inline int GetVobi(int id) { return id & 0xFF; }
	
    /** loads a project file */
	bool Open(wxString fname);
    /** saves a project file */
	bool Save(wxString fname);
    
    /** saves a configuration for dvdauthor */
	bool SaveDVDAuthor(wxString fname);
    
	/** returns estimated size of DVD im Kb */
	int GetSize(bool generated = false);
	
	/**
	 *  returns number of g-register that will be used to implement "play all"
	 *  or -1 if we don't need "play all"
	 */
	inline int GetPlayAllRegister() { return m_playAllRegister; }
	
	/** returns video format of DVD */
	inline VideoFormat GetVideoFormat() { return m_videoFormat; }
	/** sets video format of DVD */
	void SetVideoFormat(VideoFormat format) { m_videoFormat = format; }
	/** returns audio format of DVD */
	inline AudioFormat GetAudioFormat() { return m_audioFormat; }
	/** sets audio format of DVD */
	void SetAudioFormat(AudioFormat format) { m_audioFormat = format; }
	
	static wxArrayString GetVideoFormatStrings();
	static wxArrayString GetAudioFormatStrings();
	
  protected:
    wxString m_name;
	bool m_jumppad;
	bool m_emptyMenu;
	TitlesetArray m_titlesets;
	Vmgm m_vmgm;
	int m_playAllRegister;
	VideoFormat m_videoFormat;
	AudioFormat m_audioFormat;
	/** Returns true if some of buttons have flag "Play All" checked */
	bool HasPlayAllButton();
	/** Returns number of g-regsiter that is not used */
	int FindFreeRegister();
	/** Returns true if given g-register is used in pgc pre/post or in menu button action */
	bool IsRegisterUsed(int g);
};

#endif //DVDAUTHOR_H
