//**************************************************************************
//*                     This file is part of the                           *
//*                MMC - Mpxplay Multimedia Commander                      *
//*                   The source code of MMC is                            *
//*        (C) copyright 1998-2016 by PDSoft (Attila Padar)                *
//*                http://mpxplay.sourceforge.net                          *
//*                  email: mpxplay@freemail.hu                            *
//**************************************************************************
//*  This program 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.                  *
//*  Please contact with the author (with me) if you want to use           *
//*  or modify this source.                                                *
//**************************************************************************
//function: video surface context menu

//#define MPXPLAY_USE_DEBUGF 1
#define DISPQT_DEBUG_OUTPUT NULL //stdout
#define DISPQT_DEBUGOUT_EVENT NULL // stdout
#define DISPQT_DEBUGOUT_CURSOR NULL //stdout
#define DISPQT_DEBUGOUT_ACTION stdout

#include <QtGui>
#include <QtWidgets>
#include "moc_video_qt.h"
#include "moc_mainwindow.h"

extern "C" {
 extern unsigned long mpxplay_config_videoplayer_type;
#ifdef MPXPLAY_LINK_ORIGINAL_FFMPEG
 extern unsigned long mpxplay_config_video_audiovisualization_type;
#endif
 extern keyconfig kb[];
}

#ifdef MPXPLAY_LINK_ORIGINAL_FFMPEG
static const char *audio_visualization_names[DISPQT_AUDIOVISUALIZATIONTYPE_MAX] = {"Disable", "Avectorscope", "ShowFreqs", "ShowSpectrum", "ShowCQT", "ShowWaves"};  // shall match with DISPQT_AUDIOVISUALIZATIONTYPE_
static const char *video_aspectratio_names[DISPQT_VIDEOFULLSCREENARTYPE_MAX] = {""/*none*/,"Video","Window","4:3","16:9","2.35:1","1:1",""/*custom*/,"Pixel"};
static const char *video_crop_names[DISPQT_VIDEOSCRCROPTYPE_MAX] = {"None","Auto","4:3","16:9","2.35:1",""/*custom*/};
static const char *video_zoom_names[DISPQT_VIDEOFULLSCREENZOOMTYPE_MAX] = {"Touch window inside", "Touch window outside", "1:1 Original","2:1 Double","4:1 Quadruple",""/*custom*/,"Zoom In   (Ctrl-Wheel-Up)","Zoom Out (Ctrl-Wheel-Dn)"};
static const char *video_deinterlace_names[DISPQT_VIDEO_DEINTERLACETYPE_MAX] = {"Auto", "Disable", "Enable"}; // shall match with DISPQT_VIDEO_DEINTERLACETYPE_ order
static const char *video_rotation_names[DISPQT_VIDEO_ROTATIONTYPE_MAX] = {"Auto", "Disable", "Left 90", "Right 90", "Right 180"}; // shall match with DISPQT_VIDEO_ROTATIONTYPE_ order
#endif

DispQtVideoSurfaceContextMenu::DispQtVideoSurfaceContextMenu(MainWindow *main_window, DispQtVideoEventFilter *parent, QWidget *filtered) : QMenu(filtered)
{
	struct mmc_dispqt_config_s *gcfg = main_window->gui_config;

	this->main_window = main_window;
	this->parent_object = parent;
	this->filtered_widget = filtered;

	this->program_list = NULL;
	this->stream_list = NULL;
#ifdef MPXPLAY_LINK_ORIGINAL_FFMPEG
	parent->video_callback_call(-1, -1, MPXPLAY_INFILE_CBKCTRL_GET_PROGRAMLIST, &this->program_list, NULL);
	parent->video_callback_call(-1, -1, MPXPLAY_INFILE_CBKCTRL_GET_STREAMLIST, &this->stream_list, NULL);
#endif

	this->setStyleSheet("QMenu { font-size:13px; border: 1px solid transparent;}");

	//this->menuaction_filename = this->video_surface_contextmenu->addAction("");
	//this->menuaction_filename->setFont(QFont("", -1, QFont::DemiBold, false));
	//this->addSeparator();

	action_play_start = this->addAction(QIcon(":/images/player_play.png"), tr("&Play / Pause"));
	action_play_start->setShortcut(QKeySequence(tr("P")));
	action_play_stop = this->addAction(QIcon(":/images/player_stop.png"), tr("&Stop playing"));
	action_play_stop->setShortcut(QKeySequence(tr("S")));
	action_play_skipback = this->addAction(QIcon(":/images/player_skip_back.png"), tr("&Skip back"));
	action_play_skipback->setShortcut(QKeySequence(tr("-")));
	action_play_skipforward = this->addAction(QIcon(":/images/player_skip_forward.png"), tr("&Skip forward"));
	action_play_skipforward->setShortcut(QKeySequence(tr("+")));
	action_view_videofs = this->addAction(QIcon(":/images/monitor_green.png"), tr("&Fullscreen switch"));
	action_view_videofs->setShortcut(QKeySequence(tr("Alt+Enter")));
	connect(action_view_videofs, SIGNAL(triggered()), main_window, SLOT(actfunc_options_videofs()));
	this->addSeparator();

	connect(action_play_start, SIGNAL(triggered()), this, SLOT(play_start_or_pause()));
	connect(action_play_stop, SIGNAL(triggered()), main_window, SLOT(play_stop()));
	connect(action_play_skipback, SIGNAL(triggered()), main_window, SLOT(play_skip_back()));
	connect(action_play_skipforward, SIGNAL(triggered()), main_window, SLOT(play_skip_forward()));

	//------------------------------------------------------------------------------------------------------
#ifdef MPXPLAY_LINK_ORIGINAL_FFMPEG

	if(mpxplay_config_videoplayer_type == MPXPLAY_VIDEOPLAYERTYPE_FFMPEG)
	{
		this->videocontmenu_sub_audio = this->addMenu("Audio");
		this->videocontmenu_subaudio_sub_visualization = this->videocontmenu_sub_audio->addMenu("Visualization");
		for(int i = 0; i < DISPQT_AUDIOVISUALIZATIONTYPE_MAX; i++)
		{
			const char *visual_name = audio_visualization_names[i];
			if(i == mpxplay_config_video_audiovisualization_type)
				this->actions_audio_visualization_select[i] = this->videocontmenu_subaudio_sub_visualization->addAction(QIcon(":/images/tick.png"), QString::fromLatin1(visual_name));
			else
				this->actions_audio_visualization_select[i] = this->videocontmenu_subaudio_sub_visualization->addAction(QString::fromLatin1(visual_name));
		}
		connect(this->videocontmenu_subaudio_sub_visualization, SIGNAL(triggered(QAction *)), SLOT(actfunc_audio_visualization_select(QAction *)));
	}

	//------------------------------------------------------------------------------------------------------

	if(this->program_list && this->program_list->nb_programs && this->program_list->program_names)
	{
		this->actions_program_select = new QAction *[this->program_list->nb_programs];
		if(this->actions_program_select)
		{
			this->videocontmenu_sub_programs = this->addMenu("Program");
			for(int p_entry_i = 0; p_entry_i < this->program_list->nb_programs; p_entry_i++)
			{
				char *program_name = this->program_list->program_names[p_entry_i];
				if(p_entry_i == this->program_list->selected_prognum)
					this->actions_program_select[p_entry_i] = this->videocontmenu_sub_programs->addAction(QIcon(":/images/tick.png"), QString::fromUtf8(program_name));
				else
					this->actions_program_select[p_entry_i] = this->videocontmenu_sub_programs->addAction(QString::fromUtf8(program_name));
			}
			connect(this->videocontmenu_sub_programs, SIGNAL(triggered(QAction *)), SLOT(actfunc_video_program_select(QAction *)));
		}
	}

	//------------------------------------------------------------------------------------------------------

	if(this->stream_list)
	{
		this->videocontmenu_sub_streams = this->addMenu("Streams");
		for(int streamtype = 0; streamtype < MPXPLAY_STREAMTYPEINDEX_NUM; streamtype++)
		{
			unsigned int nb_streamtype_entries = this->stream_list->nb_entries[streamtype];
			if(!nb_streamtype_entries || !this->stream_list->stream_names[streamtype])
				continue;
			this->actions_stream_select[streamtype] = new QAction *[nb_streamtype_entries];
			if(!this->actions_stream_select[streamtype])
				continue;
			if(streamtype > 0)
				this->videocontmenu_sub_streams->addSeparator();
			for(int s_entry_i = 0; s_entry_i < nb_streamtype_entries; s_entry_i++)
			{
				char *stream_name = this->stream_list->stream_names[streamtype][s_entry_i];
				if(this->stream_list->stream_idx[streamtype][s_entry_i] == this->stream_list->selected_stream_index[streamtype])
					this->actions_stream_select[streamtype][s_entry_i] = this->videocontmenu_sub_streams->addAction(QIcon(":/images/tick.png"), QString::fromUtf8(stream_name));
				else
					this->actions_stream_select[streamtype][s_entry_i] = this->videocontmenu_sub_streams->addAction(QString::fromUtf8(stream_name));
			}
		}
		connect(this->videocontmenu_sub_streams, SIGNAL(triggered(QAction *)), SLOT(actfunc_video_stream_select(QAction *)));
	}

	//------------------------------------------------------------------------------------------------------

	if(mpxplay_config_videoplayer_type == MPXPLAY_VIDEOPLAYERTYPE_FFMPEG)
	{
		this->videocontmenu_sub_video = this->addMenu("Video");

		this->videocontmenu_subvideo_sub_aspectratio = this->videocontmenu_sub_video->addMenu("Aspect ratio");
		for(int i = DISPQT_VIDEOFULLSCREENARTYPE_FIRST; i < DISPQT_VIDEOFULLSCREENARTYPE_MAX; i++){
			const char *ratio_name = (i == DISPQT_VIDEOFULLSCREENARTYPE_CUSTOM)? &gcfg->video_ar_custom[0] : video_aspectratio_names[i];
			if(i == gcfg->video_fullscreen_ar_type)
				this->actions_video_ar_select[i] = this->videocontmenu_subvideo_sub_aspectratio->addAction(QIcon(":/images/tick.png"), QString::fromLatin1(ratio_name));
			else
				this->actions_video_ar_select[i] = this->videocontmenu_subvideo_sub_aspectratio->addAction(QString::fromLatin1(ratio_name));
		}
		connect(this->videocontmenu_subvideo_sub_aspectratio, SIGNAL(triggered(QAction *)), SLOT(actfunc_video_ar_select(QAction *)));

		this->videocontmenu_subvideo_sub_crop = this->videocontmenu_sub_video->addMenu("Crop");
		for(int i = 0; i < DISPQT_VIDEOSCRCROPTYPE_MAX; i++){
			const char *crop_name = (i == DISPQT_VIDEOSCRCROPTYPE_CUSTOM)? &gcfg->video_crop_custom[0] : video_crop_names[i];
			if(i == gcfg->video_crop_type)
				this->actions_video_crop_select[i] = this->videocontmenu_subvideo_sub_crop->addAction(QIcon(":/images/tick.png"), QString::fromLatin1(crop_name));
			else
				this->actions_video_crop_select[i] = this->videocontmenu_subvideo_sub_crop->addAction(QString::fromLatin1(crop_name));
		}
		connect(this->videocontmenu_subvideo_sub_crop, SIGNAL(triggered(QAction *)), SLOT(actfunc_video_crop_select(QAction *)));

		this->videocontmenu_subvideo_sub_deinterlace = this->videocontmenu_sub_video->addMenu("Deinterlace");
		for(int i = 0; i < DISPQT_VIDEO_DEINTERLACETYPE_MAX; i++){
			const char *deint_name = video_deinterlace_names[i];
			if(i == gcfg->video_deinterlace_type)
				this->actions_video_deinterlace_select[i] = this->videocontmenu_subvideo_sub_deinterlace->addAction(QIcon(":/images/tick.png"), QString::fromLatin1(deint_name));
			else
				this->actions_video_deinterlace_select[i] = this->videocontmenu_subvideo_sub_deinterlace->addAction(QString::fromLatin1(deint_name));
		}
		connect(this->videocontmenu_subvideo_sub_deinterlace, SIGNAL(triggered(QAction *)), SLOT(actfunc_video_deinterlace_select(QAction *)));

		this->videocontmenu_subvideo_sub_rotation = this->videocontmenu_sub_video->addMenu("Rotation");
		for(int i = 0; i < DISPQT_VIDEO_ROTATIONTYPE_MAX; i++){
			const char *rotat_name = video_rotation_names[i];
			if(i == gcfg->video_rotation_type)
				this->actions_video_rotation_select[i] = this->videocontmenu_subvideo_sub_rotation->addAction(QIcon(":/images/tick.png"), QString::fromLatin1(rotat_name));
			else
				this->actions_video_rotation_select[i] = this->videocontmenu_subvideo_sub_rotation->addAction(QString::fromLatin1(rotat_name));
		}
		connect(this->videocontmenu_subvideo_sub_rotation, SIGNAL(triggered(QAction *)), SLOT(actfunc_video_rotation_select(QAction *)));

		this->videocontmenu_subvideo_sub_zoom = this->videocontmenu_sub_video->addMenu("Zoom");
		for(int i = 0; i <= DISPQT_VIDEOFULLSCREENZOOMTYPE_MENUACTIONS; i++){
			const char *zoom_name = (i == DISPQT_VIDEOFULLSCREENZOOMTYPE_CUSTOM)? &gcfg->video_zoom_custom[0] : video_zoom_names[i];
			if(i == gcfg->video_zoom_type)
				this->actions_video_zoom_select[i] = this->videocontmenu_subvideo_sub_zoom->addAction(QIcon(":/images/tick.png"), QString::fromLatin1(zoom_name));
			else
				this->actions_video_zoom_select[i] = this->videocontmenu_subvideo_sub_zoom->addAction(QString::fromLatin1(zoom_name));
		}
		connect(this->videocontmenu_subvideo_sub_zoom, SIGNAL(triggered(QAction *)), SLOT(actfunc_video_zoom_select(QAction *)));
	}

	//------------------------------------------------------------------------------------------------------
	this->addSeparator();

#endif // MPXPLAY_LINK_ORIGINAL_FFMPEG

	action_file_exit = this->addAction(tr("E&xit"));
	connect(action_file_exit, SIGNAL(triggered()), this, SLOT(program_exit()));
}

#ifdef MPXPLAY_LINK_ORIGINAL_FFMPEG
static void DispQtVideoSurfaceContextMenu_programlist_free(struct mpxplay_programinfo_t *prg_list)
{
	if(prg_list){
		if(prg_list->program_names){
			int i;
			for(i = 0; i < prg_list->nb_programs; i++)
				if(prg_list->program_names[i])
					pds_free(prg_list->program_names[i]);
			pds_free(prg_list->program_names);
		}
		if(prg_list->program_ids)
			pds_free(prg_list->program_ids);
		pds_free(prg_list);
	}
}

static void DispQtVideoSurfaceContextMenu_streamlist_free(struct mpxplay_streaminfo_t *strm_list)
{
	if(strm_list)
	{
		int t;
		for(t = 0; t < MPXPLAY_STREAMTYPEINDEX_NUM; t++){
			if(strm_list->stream_names[t]){
				int i;
				for(i = 0; i < strm_list->nb_entries[t]; i++)
					if(strm_list->stream_names[t][i])
						pds_free(strm_list->stream_names[t][i]);
				pds_free(strm_list->stream_names[t]);
			}
			if(strm_list->stream_idx[t])
				pds_free(strm_list->stream_idx[t]);
		}
		pds_free(strm_list);
	}
}
#endif

DispQtVideoSurfaceContextMenu::~DispQtVideoSurfaceContextMenu()
{
#ifdef MPXPLAY_LINK_ORIGINAL_FFMPEG
	DispQtVideoSurfaceContextMenu_programlist_free(this->program_list);
	DispQtVideoSurfaceContextMenu_streamlist_free(this->stream_list);
#endif
}

void DispQtVideoSurfaceContextMenu::mouseReleaseEvent(QMouseEvent *mevent)
{
	if(mevent->button() & (Qt::MouseButton::RightButton | Qt::MouseButton::MiddleButton)) // we don't accept right and mid buttons in video context menu (to avoid unwanted effect/actions)
		mevent->accept();
	else
		QMenu::mouseReleaseEvent(mevent);
}

void DispQtVideoSurfaceContextMenu::play_start_or_pause(void)
{
	pds_pushkey(kb[50].c); // KeyPlayPause1
}

void DispQtVideoSurfaceContextMenu::program_exit(void)
{
	pds_pushkey(kb[32].c); // KeyExit3 (exit without shutdown)
}

#ifdef MPXPLAY_LINK_ORIGINAL_FFMPEG
void DispQtVideoSurfaceContextMenu::actfunc_audio_visualization_select(QAction *selected_visualization_action)
{
	for(int i = 0; i < DISPQT_AUDIOVISUALIZATIONTYPE_MAX; i++){
		if(selected_visualization_action == this->actions_audio_visualization_select[i]){
			mpxplay_config_video_audiovisualization_type = i;
			emit this->main_window->qt_video_player->signal_ffmpeg_config_callback(MPXPLAY_INFILE_CBKCFG_SRVFFMV_REFRESH_CALLBACK, NULL, NULL);
			mpxplay_debugf(DISPQT_DEBUGOUT_ACTION, "actfunc_audio_visualization_select i:%d s:%8.8X a:%8.8X", i, (int)selected_visualization_action, (int)this->actions_audio_visualization_select[i]);
			break;
		}
	}
}

void DispQtVideoSurfaceContextMenu::actfunc_video_ar_select(QAction *selected_ar_action)
{
	for(int i = DISPQT_VIDEOFULLSCREENARTYPE_FIRST; i < DISPQT_VIDEOFULLSCREENARTYPE_MAX; i++){
		if(selected_ar_action == this->actions_video_ar_select[i]){
			this->main_window->gui_config->video_fullscreen_ar_type = i;
			emit this->main_window->qt_video_player->signal_video_surface_resize_refresh();
			mpxplay_debugf(DISPQT_DEBUGOUT_ACTION, "actfunc_video_ar_select i:%d s:%8.8X a:%8.8X", i, (int)selected_ar_action, (int)this->actions_video_ar_select[i]);
			break;
		}
	}
}

void DispQtVideoSurfaceContextMenu::actfunc_video_crop_select(QAction *selected_crop_action)
{
	for(int i = 0; i < DISPQT_VIDEOSCRCROPTYPE_MAX; i++){
		if(selected_crop_action == this->actions_video_crop_select[i]){
			this->main_window->gui_config->video_crop_type = i;
			emit this->main_window->qt_video_player->signal_video_surface_resize_refresh();
			mpxplay_debugf(DISPQT_DEBUGOUT_ACTION, "actfunc_video_crop_select i:%d s:%8.8X a:%8.8X", i, (int)selected_crop_action, (int)this->actions_video_crop_select[i]);
			break;
		}
	}
}

void DispQtVideoSurfaceContextMenu::actfunc_video_deinterlace_select(QAction *selected_deinterlace_action)
{
	for(int i = 0; i < DISPQT_VIDEO_DEINTERLACETYPE_MAX; i++){
		if(selected_deinterlace_action == this->actions_video_deinterlace_select[i]){
			this->main_window->gui_config->video_deinterlace_type = i;
			mpxplay_debugf(DISPQT_DEBUGOUT_ACTION, "actfunc_video_deinterlace_select i:%d s:%8.8X a:%8.8X", i, (int)selected_deinterlace_action, (int)this->actions_video_deinterlace_select[i]);
			break;
		}
	}
}

void DispQtVideoSurfaceContextMenu::actfunc_video_rotation_select(QAction *selected_rotation_action)
{
	for(int i = 0; i < DISPQT_VIDEO_ROTATIONTYPE_MAX; i++){
		if(selected_rotation_action == this->actions_video_rotation_select[i]){
			this->main_window->gui_config->video_rotation_type = i;
			emit this->main_window->qt_video_player->signal_video_surface_filtered_trans_refresh();
			mpxplay_debugf(DISPQT_DEBUGOUT_ACTION, "actfunc_video_rotation_select i:%d s:%8.8X a:%8.8X", i, (int)selected_rotation_action, (int)this->actions_video_rotation_select[i]);
			break;
		}
	}
}

void DispQtVideoSurfaceContextMenu::actfunc_video_zoom_select(QAction *selected_zoom_action)
{
	for(int i = 0; i <= DISPQT_VIDEOFULLSCREENZOOMTYPE_MENUACTIONS; i++){
		if(selected_zoom_action == this->actions_video_zoom_select[i]){
			if(i <= DISPQT_VIDEOFULLSCREENZOOMTYPE_SETTINGS){
				this->main_window->gui_config->video_zoom_type = i;
				emit this->main_window->qt_video_player->signal_video_surface_resize_refresh();
			}else if(i == DISPQT_VIDEOFULLSCREENZOOMTYPE_ZOOMIN)
				this->parent_object->video_zoom_step(-1,-1, 1);
			else if(i == DISPQT_VIDEOFULLSCREENZOOMTYPE_ZOOMOUT)
				this->parent_object->video_zoom_step(-1, -1, -1);
			mpxplay_debugf(DISPQT_DEBUGOUT_ACTION, "actfunc_video_ar_select i:%d s:%8.8X a:%8.8X", i, (int)selected_zoom_action, (int)this->actions_video_zoom_select[i]);
			break;
		}
	}
}

void DispQtVideoSurfaceContextMenu::actfunc_video_program_select(QAction *selected_program_action)
{
	if(!this->program_list)
		return;
	for(int p_entry_i = 0; p_entry_i < this->program_list->nb_programs; p_entry_i++){
		if(selected_program_action == this->actions_program_select[p_entry_i]){
			this->parent_object->video_callback_call(-1, -1, MPXPLAY_INFILE_CBKCTRL_SET_SELECT_PROGRAM, &this->program_list->program_ids[p_entry_i], NULL);
			return;
		}
	}
}

void DispQtVideoSurfaceContextMenu::actfunc_video_stream_select(QAction *selected_stream_action)
{
	int streamtype;
	if(!this->stream_list)
		return;
	for(streamtype = 0; streamtype < MPXPLAY_STREAMTYPEINDEX_NUM; streamtype++){
		unsigned int nb_streamtype_entries = this->stream_list->nb_entries[streamtype];
		for(int s_entry_i = 0; s_entry_i < nb_streamtype_entries; s_entry_i++){
			if(selected_stream_action == this->actions_stream_select[streamtype][s_entry_i]){
				this->stream_list->selected_stream_index[streamtype] = (streamtype == MPXPLAY_STREAMTYPEINDEX_SUBTITLE)? (s_entry_i - 1) : s_entry_i; // TODO: subtitle index hack
				this->parent_object->video_callback_call(-1, -1, MPXPLAY_INFILE_CBKCTRL_SET_SELECT_STREAM, &streamtype, &this->stream_list->selected_stream_index[streamtype]);
				return;
			}
		}
	}
}
#endif // MPXPLAY_LINK_ORIGINAL_FFMPEG
