/*****************************************************************************
 *
 *  playerwidget.h -- Container for player controls.
 *
 *  Copyright (C) 2010 Starbuck <starbuck@labdv.com>
 *  All rights reserved.
 *
 *  This file is part of the Gui4 module of the DVDx 4 application.
 *
 *  GNU Lesser General Public License Usage
 *  This file may be used under the terms of the GNU Lesser General
 *  Public License version 2.1 as published by the Free Software
 *  Foundation and appearing in the file LICENSE.LGPL included in the
 *  packaging of this file.  Please review the following information to
 *  ensure the GNU Lesser General Public License version 2.1 requirements
 *  will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 *
 *  GNU General Public License Usage
 *  Alternatively, this file may be used under the terms of the GNU
 *  General Public License version 3.0 as published by the Free Software
 *  Foundation and appearing in the file LICENSE.GPL included in the
 *  packaging of this file.  Please review the following information to
 *  ensure the GNU General Public License version 3.0 requirements will be
 *  met: http://www.gnu.org/copyleft/gpl.html.
 *
 *****************************************************************************/

#ifndef PLAYERWIDGET_H
#define PLAYERWIDGET_H

#include "../video/video_struct.h"
#include "../player/player.h"
#include "timecodewidget.h"
#include "progresswidget.h"

#include <QWidget>
#include <QProcess>
#include <QLabel>
#include <QPushButton>
#include <QCheckBox>
#include <QComboBox>
#include <QGroupBox>
#include <QTextEdit>
#include <QSlider>
#include <QStringList>
#include <QTimer>

class PlayerWidget: public QWidget
{
	Q_OBJECT
	 
public:
	struct Preferences
	{
		bool test_mode;
		int test_frames;
		int test_chapter;
		int test_position;

		int volume_correction;

		bool dvd_ignore_short_titles;
		double dvd_title_min_length;

		int auto_zoom_max_width;
		int auto_zoom_max_height;

		int latency_start;
		int latency_finished;
		int latency_kill;

		int poll_ticks;

		int maximum_errors;
		int maximum_repetead_errors;
		int maximum_loading_errors;

		Preferences() { reset(); }

		void reset()
		{
			test_mode = false;
			test_frames = 1000;		// MUST be the same as EncoderWidget::Preferences
			test_chapter = 4;		// MUST be the same as EncoderWidget::Preferences
			test_position = 12;		// MUST be the same as EncoderWidget::Preferences

			volume_correction = 0;	// MUST be the same as EncoderWidget::Preferences

			dvd_ignore_short_titles = true; 
			dvd_title_min_length = 600;

			auto_zoom_max_width = 512;
			auto_zoom_max_height = 288;

#ifdef Q_OS_MAC
			latency_start = 5000;
			latency_finished = 5000;
#else
			latency_start = 3000;
			latency_finished = 3000;
#endif
			latency_kill = 5000;

			poll_ticks = 500;

			maximum_errors = 500;
			maximum_repetead_errors = 100;
			maximum_loading_errors = 100;
		}
	};

	PlayerWidget(QWidget *, const QString &, const QString &, const QString &,
		QTextEdit *, QTextEdit *, QTextEdit *, QTextEdit *, const int, 
		Preferences *prefs=0, QWidget *parent=0);
	~PlayerWidget();

	void getStatus(bool *, bool *, bool *);

	void enablePlaybackControls(const bool);
	void enableTrackControls(const bool);

	inline bool isLoaded() const { return isMovieLoaded->checkState() == Qt::Checked; };

	void playRequest();
	void stopRequest();

	QSize renderSize();
	QString currentAspectRatio();  // returns current title or movie aspect ratio 
	double calculateAutoZoom();

	inline void setNoChoiceInList(const bool b) { noChoiceInList = b; };
	void setVerbosity(const int);
	void setPreferences(Preferences *prefs=0);
	void setZoom(const double);
	inline void disableAutoZoom() { autoZoom = false; };
	void resetPreferences();
	void setBinPath(const QString&);
	void setMediaInfoBinPath(const QString&);
	void setFFprobeBinPath(const QString&);
	bool setInput(const QString &path, const int media = 0);
	inline bool isPlaying() const { return runPlaying; };
	bool isReady(const bool refresh=false);
	player_engine_status_t readStatus();
	player_engine_capability_t readCapability();
	utility_status_t readMediaInfoStatus();
	interfacemediainfo_data_t readMediaInfoData();
	utility_status_t readFFprobeStatus();
	interfaceffprobe_t readFFprobeData();

	inline QString enginePath(const int engine) const { return player->getBinPath(engine); };
	inline QString engineVersion(const int engine) const { return player->engineVersion(engine); };

	inline int currentMedia() { return media; };
	inline QString currentName() { return name; };
	inline QString currentMovieFormat() { return movieInfo.format; };

	void streamCount(int *, int *, int *);

	video_t currentVideo(); 
	audio_t currentAudio(); 
	subtitle_t currentSubtitle(); 

	inline bool noVideoSelected() const { return novideo; };
	inline bool noAudioSelected() const { return audio == -1; };
	inline bool noSubtitleSelected() const { return subtitle == -1; };

	inline QList<int> getAdditionalAudio() const { return additionalAudio; };
	inline QList<int> getAdditionalSubtitle() const { return additionalSubtitle; };

signals:
	void guiSizeAdjustRequest();
	void stateChanged(bool);
	void selectionChanged();

protected:
	void resizeEvent(QResizeEvent *);

protected:
	void printLog(const QString &, const int=VERBOSITY_NORMAL);
	void printIn(const QString &, const int=VERBOSITY_NORMAL);
	void printOut(const QString &, const int=VERBOSITY_NORMAL);
	void printErr(const QString &, const int=VERBOSITY_NORMAL);

	void clearLog();
	void clearIn();
	void clearOut();
	void clearErr();

	bool start();
	bool stop();
	void setRunPlaying(const bool);

	bool loadFile(const QString &);
	bool loadDvd(const QString &);
	bool openDvd(const QString &);

	void clearTrackControls();
	void decorateController();
	void populateTrackControls();
	void populateTrackControlsAud(const int);
	void populateTrackControlsSub(const int);
	void populateTrackControlsAng(const int);
	void populateTrackControlsAud(const movie_t &);
	void populateTrackControlsSub(const movie_t &);
	void populateTrackControlsAng(const movie_t &);

	void setTransparentBackground(const bool);
	
protected slots:
	void playerEnded(int exitCode, QProcess::ExitStatus exitStatus);
	void pollCurrentTime();
	void readStandardOutput();
	void readStandardError();
	void monitorPlaybackErrors();
	void timeLineChanged(int pos);

	void switchState();
	void switchPause();
	void switchFaster();
	void switchSlower();
	void prevChapter();
	void nextChapter();
	void prev();
	void next();

	void selectTitleByUser(int);
	void selectTitle(int);
	void selectAudio(int);
	void selectSubtitle(int);
	void selectAngle(int);

	void setListToolTips();

	void processBridgeMessage(const QString &, const bool);
	void processBridgeMessage(const QString &, const int);

	void centerRenderer();
	void updateControlsOnLoading(int);

	void stopLoadDvd();
	void stopUpdateFontCache();

protected:
	QWidget *mainConsole;	// for centering/sizing/moving child windows
	Player *player;		// player interface (must be used only for the renderer)

	QString binPath;	// path to player binary (required for every player instance)
	QString mediainfoBinPath;
	QString ffprobeBinPath;

	int verbosity;
	ProgressWidget *progressBar;
	
	QTextEdit *log;				// log application errors/warnings
	QTextEdit *standardInput;	// process stdIn
	QTextEdit *standardOutput;	// process stdOut
	QTextEdit *standardError;	// process stdErr

	QIcon *playIcon;
	QIcon *playFastIcon;
	QIcon *playExcerptIcon;
	QIcon *playExcerptFastIcon;
	QIcon *stopIcon;
	QIcon *stopExcerptIcon;
	QIcon *slowIcon;
	QIcon *slowExcerptIcon;
	QIcon *fastIcon;
	QIcon *fastExcerptIcon;

	QPushButton *controller;	// start/stop/"normal speed" button
	QPushButton *pauseButton;
	QPushButton *slowerButton;
	QPushButton *fasterButton;
	QPushButton *prevChapterButton;
	QPushButton *nextChapterButton;
	QPushButton *prevButton;
	QPushButton *nextButton;
	QLabel *chapterDisplay;
	TimecodeWidget *timecodeDisplay;
	QFrame *renderTV;
	QFrame *renderTarget;		// the renderer will be in a 16:9 TV
	QLabel *renderBackground;
	QPixmap *audioPixmap;
	QProcess *playerProcess;	// must be used only for the renderer

	int refChapter;
	double refPosition;

	player_engine_capability_t *playerCapability;
	player_engine_status_t *playerStatus;
	utility_status_t *mediaInfoStatus;
	interfacemediainfo_data_t *mediaInfoData;
	utility_status_t *ffprobeStatus;
	interfaceffprobe_t *ffprobeData;

	QGroupBox *trackGroup;
	QComboBox *titleList;
	QComboBox *audioList;
	QComboBox *subtitleList;
	QComboBox *angleList;

	QSlider *timeLine;
	QTimer *poller;

	bool userStopUpdateFontCache;
	bool userStopLoadDvd;
	QCheckBox *isMovieLoaded;	// tri-state flag:	NotLoaded = Qt::Unchecked
								//					Loading = Qt::PartiallyChecked 
								//					Loaded = Qt::Checked 
	
	bool runPlaying;
	bool runNormalSpeed;

	double playPos;		// current position in the file in seconds
	double playLength;	// length of the current file in seconds.
	bool playMute;		// sound output muting
	bool playPause;		// pause/unpaused playback
	double playSpeed;	// current playback speed (0.01 to 100)

	QString current;
	QString name;		// for DVD: volume identifier, for movie: file name
	QString movie;		// path to movie (or -dvd-device)
	bool novideo;		// ignore video stream (audio file)
	int media;			// media type: file, dvd, vcd, tv etc...
	int longest;		// longest title (main title)
	int title;			// DVD title to play	[index+1 in titleInfo]
	int chapter;		// DVD chapter to play	[0 for all]
	int currentChapter;	// current chapter during playback
	int audio;			// audio stream to play	[index in audio of titleInfo]
	int subtitle;		// subtitle to display	[index in subtitle of titleInfo]
	int angle;			// DVD angle to play
	
	QSize scaledResolutionReference;	// current movie/title 1:1 resolution
	QSize scaledResolution;	
	double zoom;
	bool autoZoom;

	QList<int> additionalAudio;		// multi audio streams
	QList<int> additionalSubtitle;	// multi subtitle streams

	int titles;					// number of titles in current DVD
	QList<title_t> titleInfo;	// info for DVD titles
	movie_t movieInfo;			// info for movie file (not a DVD)
								// audio files are movie with codec == ""

	QList<slice_t> sliceCut;  // list of chapters or parts to play

	int chapters;		// number of chapters in current DVD title
	int angles;			// number of angles in current DVD title
	int audios;			// number of audio streams in current DVD title
	int subtitles;		// number of subtitles in current DVD title

	bool noChoiceInList;	// true to disply "No video" and "No audio" choices when possible

	QList<QString> *playbackErrors;

	Preferences preferences;
};

#endif
