#include <IV-look/kit.h>
#include <InterViews/event.h>
#include <InterViews/action.h>
#include <InterViews/background.h>
#include <InterViews/layout.h>
#include <InterViews/session.h>
#include <InterViews/color.h>
#include <InterViews/border.h>
#include <InterViews/style.h>
#include <InterViews/window.h>
#include <X11/cursorfont.h>
#include <X11/keysym.h>
#include <string.h>
#include "iv_graph.h"
#include "dsp_app.h"
#include "genmenu.h"
#include "cgidbg.h"
#include "plotdatg.h"
#include "mkstr.h"
#include "portable.h"
#include "xk_tab.h"
#include <InterViews/enter-scope.h>
#include <OS/enter-scope.h>

class WindowMenuGraph: public WindowMenu {
	int view_allowed ;
	Graph * the_graph ;
	void check_release();
	DataPlot * plot ;

	int is_eye_plot() {return plot->is_eye_plot();}
	void clear_view_allowed() {view_allowed = 0 ;}
	virtual Action * set_action(PullDownEntry * i) ;
public:
	WindowMenuGraph(Graph * gr,DataPlot *plt):
		WindowMenu(),
		view_allowed(1),
		the_graph(gr),plot(plt){}
	Graph * graph() const {return the_graph;}
	void help_detail();
	void help_view();
	void help_value();

	virtual void clear_selected() {}

	void more_detail();
	void more_detail_x();
	void more_detail_y();

	void less_detail();
	void less_detail_x();
	void less_detail_y();

	void eye_plot_samples();

	void restore_original();
	void restore_previous();

	void PageUp();
	void PageDown();
	void ShiftEnd();
	void End();
	void to_time();
	void to_sample();
	void ahead_time();
	void ahead_samples();

	void db_view();
	void power_view();
	void db_power_view();
	void copy();
	void save_plot();
	void save_window();

};


void WindowMenuGraph::check_release()
{
	the_graph->menu_keyboard()->check_release();
}

typedef void (WindowMenuGraph::*ActionType)();
class ActionWindowMenuGraph: public RecAction {
	WindowMenuGraph * gr ;
	ActionType the_action ;
public:
	ActionWindowMenuGraph(MenuKeyboard * k, WindowMenuGraph * g,
		PullDownEntry& desc, ActionType a);
	ActionWindowMenuGraph(ActionType a):RecAction(0,0),the_action(a){}
	void force_execute() {record(); (gr->*the_action)();}
	void execute();
	ActionType action() {return the_action;}
};

ActionWindowMenuGraph::ActionWindowMenuGraph(MenuKeyboard * k,
	WindowMenuGraph * g, PullDownEntry& desc, ActionType a):
	RecAction(k,&desc),
	gr(g),
	the_action(a)
{
	Resource::ref(this);
}

void ActionWindowMenuGraph::execute()
{
	if (!DspApplication::user_input_allowed()) return ;
	record();
	(gr->*the_action)();
}

#define declare_WindowMenuGraph_member(name) \
static ActionWindowMenuGraph name (&(WindowMenuGraph::name)) ; \
void WindowMenuGraph::name()
	

declare_WindowMenuGraph_member(help_detail)
{
	check_release();
	DspApplication::display_help_file("plot_detail");
	// LogOut << "help_detail\n" ;
}

declare_WindowMenuGraph_member(help_view)
{
	DspApplication::display_help_file("plot_view");
	check_release();
	// LogOut << "help_view\n" ;
}

declare_WindowMenuGraph_member(help_value)
{
	DspApplication::display_help_file("plot_value");
	check_release();
	// LogOut << "help_value\n" ;
}


declare_WindowMenuGraph_member(more_detail)
{
	check_release();
	// LogOut << "more_detail\n" ;
	the_graph->resize(XK_Up,XC_draft_large);
}

declare_WindowMenuGraph_member(more_detail_x)
{
	check_release();
	// LogOut << "more_detail_x\n" ;
	the_graph->resize(XK_FUNCTION_FLAG | XK_Right,XC_sb_right_arrow);
}

declare_WindowMenuGraph_member(more_detail_y)
{
	check_release();
	// LogOut << "more_detail_y\n" ;
	the_graph->resize(XK_FUNCTION_FLAG | XK_Up,XC_sb_up_arrow);
}


declare_WindowMenuGraph_member(less_detail)
{
	check_release();
	// LogOut << "less_detail\n" ;
	the_graph->resize(XK_Down, XC_top_left_arrow);
}

declare_WindowMenuGraph_member(less_detail_x)
{
	check_release();
	// LogOut << "less_detail_x\n" ;
	the_graph->resize(XK_FUNCTION_FLAG | XK_Left,XC_sb_left_arrow);
}

declare_WindowMenuGraph_member(eye_plot_samples)
{
	check_release();
	// LogOut << "less_detail_y\n" ;
	the_graph->eye_plot_samples();
}

declare_WindowMenuGraph_member(less_detail_y)
{
	check_release();
	// LogOut << "less_detail_y\n" ;
	the_graph->resize(XK_FUNCTION_FLAG | XK_Down,XC_sb_down_arrow);
}


declare_WindowMenuGraph_member(restore_original)
{
	// LogOut << "restore_original\n" ;
	check_release();
	the_graph->home();
}

declare_WindowMenuGraph_member(restore_previous)
{
	// LogOut << "restore_previous\n" ;
	check_release();
	the_graph->shift_home();
}


declare_WindowMenuGraph_member(PageUp)
{
	check_release();
	the_graph->get_data_plot()->PageUp();
}

declare_WindowMenuGraph_member(PageDown)
{
	check_release();
	the_graph->get_data_plot()->PageDown();
}

declare_WindowMenuGraph_member(save_plot)
{
	check_release();
	the_graph->save_plot();
}

declare_WindowMenuGraph_member(save_window)
{
	check_release();
	the_graph->print_window_raise();
}

declare_WindowMenuGraph_member(ShiftEnd)
{
	check_release();
	the_graph->get_data_plot()->PageStart();
}

declare_WindowMenuGraph_member(End)
{
	check_release();
	the_graph->get_data_plot()->PageEnd();
}

declare_WindowMenuGraph_member(to_time)
{
	the_graph->to_time();
	check_release();
}

declare_WindowMenuGraph_member(to_sample)
{
	the_graph->to_sample();
	check_release();
}

declare_WindowMenuGraph_member(ahead_time)
{
	the_graph->ahead_time();
	check_release();
}

declare_WindowMenuGraph_member(ahead_samples)
{
	the_graph->ahead_samples();
	check_release();
}

declare_WindowMenuGraph_member(copy)
{
	check_release();
	graph()->get_data_plot()->clone(DataPlot::copy);
}

declare_WindowMenuGraph_member(db_view)
{
	check_release();
	if (!view_allowed) return ;
	graph()->get_data_plot()->clone(DataPlot::db);
	// LogOut << "db_view\n" ;
}

declare_WindowMenuGraph_member(power_view)
{
	check_release();
	if (!view_allowed) return ;
	graph()->get_data_plot()->clone(DataPlot::power);
	// LogOut << "power_view\n" ;
}

declare_WindowMenuGraph_member(db_power_view)
{
	check_release();
	if (!view_allowed) return ;
	graph()->get_data_plot()->clone(DataPlot::db_power);
	// LogOut << "db_power_view\n" ;
}


#define WinAction 

static PullDownDescribe help_menu[] = {
	{ "change plot detail",XK_F6,&help_detail},
	{ "change data view",XK_F7, &help_view},
	{ "locate a sample point",XK_F8, &help_value},
	{0}
};

static PullDownDescribe detail_menu[] = {
	{ "more",XK_Up + XK_c_, &more_detail},
	{ "less",XK_Down + XK_c_, &less_detail},
	{ "restore original", XK_Home, &restore_original},
	{ "restore previous",XK_Home + XK_s_, &restore_previous},
	{ nil}
};

static PullDownDescribe x_y_detail_menu[] = {
	{ "more X",XK_Right, &more_detail_x},
	{ "less X",XK_Left, &less_detail_x},
	{ "more Y",XK_Up, &more_detail_y},
	{ "less Y",XK_Down, &less_detail_y},
	{nil}, // space for eye plot entry below
	{nil}
};

static PullDownDescribe pulldown_nil =  {nil} ;
static PullDownDescribe eye_plot_samples_select = 
	{"change number of samples",XK_c_ + XK_e, &eye_plot_samples};


static PullDownDescribe position_menu[] = {
	{ "ahead one frame",XK_Next, &PageDown},
	{ "back one frame",XK_Prior, &PageUp},
	{ "first frame",XK_End + XK_s_, &ShiftEnd},
	{ "last frame", XK_End,&End},
	{ "go to time", XK_Tab, &to_time},
	{ "go to sample", XK_c_ + XK_Tab, &to_sample},
	{ "ahead (- for back) time", XK_c_ + XK_a, &ahead_time},
	{ "ahead (- for back) samples", XK_c_ + XK_A, &ahead_samples},
	{nil}
};

static PullDownDescribe the_eye_view_menu[] = {
	{ "copy original", XK_o + XK_c_, &copy},
	{ "save plot to file", XK_c_ + XK_S, &save_plot},
	{ "save window image", XK_s_ + XK_c_ + XK_8, &save_window},
	{ nil }
};
static PullDownDescribe view_menu[] = {
	{ "decibel",XK_c_ + XK_d, &db_view},
	{ "power",XK_c_ + XK_p,  &power_view},
	{ "decibel power",XK_c_ + XK_b, &db_power_view},
	{ "copy original", XK_o + XK_c_, &copy},
	{ "save plot to file", XK_c_ + XK_S, &save_plot},
	{ "save window image", XK_s_ + XK_c_ + XK_8, &save_window},
	{ nil }
};

#define view_menu_string "View"

static PullDownDescribe eye_view_menu =
	{ view_menu_string,XK_F5,nil,the_eye_view_menu};

static PullDownDescribe normal_view_menu =
	{ view_menu_string,XK_F5,nil,view_menu};

static PullDownDescribe plot_main_menu[] ={
	{ "Help",XK_F1,nil,help_menu},
	{ "Detail",XK_F2,nil,detail_menu},
	{ "X or Y detail",XK_F3,nil,x_y_detail_menu},
	{ "X position",XK_F4,nil,position_menu},
	{ nil},  // space for view menu 
	{ nil}
};

static PullDownDescribe plot_menu_tree = {0,0,0,plot_main_menu};

Action * WindowMenuGraph::set_action(PullDownEntry * i)
{
	MenuKeyboard * k = keyboard();
    WindowMenuGraph * g = this ;
	PullDownEntry& desc = *i ;
	ActionType a = ((ActionWindowMenuGraph *) i->base_action())->action();
	ActionWindowMenuGraph * this_action = new ActionWindowMenuGraph(k,g,desc,a);
/*
 *	ActionWindowMenuGraph * this_action = new ActionWindowMenuGraph(
 *		keyboard(),this,*i,
 *		((ActionWindowMenuGraph *) i->base_action())->action());
 */
	i->action(this_action);
	return this_action ;
}

MenuKeyboard * Graph::build_menu(ivWidgetKit* kit, const ivLayoutKit& layout,
	ivStyle * style, DataPlot * plt)
{
	PullDownDescribe * restore = 0 ;
	if (plt->is_eye_plot() && (plt->GetBlockSize()==1)) {
		for (restore = x_y_detail_menu; restore->str; restore++) ;
		*restore = eye_plot_samples_select;
	}

	PullDownDescribe * view_pos = 0 ;
	for (view_pos = plot_main_menu; view_pos->str; view_pos++) ;
	if (plt->is_eye_plot()) *view_pos = eye_view_menu ;
	else *view_pos = normal_view_menu ;

	WindowMenuGraph * menu_window = new WindowMenuGraph(this,plt) ;
	MenuKeyboard * ret = new MenuKeyboard(*kit, layout, style, menu_window,
		plot_menu_tree);
	if (restore) *restore = pulldown_nil ;
	if (view_pos) *view_pos = pulldown_nil ;
	return ret ;
}



