/*
 * ui.h
 * This file is part of galvani.
 * Copyright (C) 2020-2024 Burkard Lutz <b.lutz@online.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef UI_H
#define UI_H

extern std::vector<std::string> m_functions;
extern std::vector<acid_data> acid;
extern std::string datadir;
extern Project *project;

extern Glib::RefPtr<Gio::ListStore<Gtk::FileFilter>> dat_filters;
extern Glib::RefPtr<Gio::ListStore<Gtk::FileFilter>> img_filters;


class ProjectDialog : public Gtk::Dialog
{
	public:

		Gtk::Box tit_options;

		void new_project ();	//new project
		void define_project(); 	//set project settings
		void set_project_options (int response_id);
		void show_settings_device_x ();	// show project settings for channel X
		void show_settings_device_y ();	// show project settings for channel Y
		void configure_settings_device_x();	// configure options for channel X and show in project
		void configure_settings_device_y();	// configure options for channel Y and show in project
		void show_tit_options();		//show options for simulation of titration curve
		int get_acid_index(std::string name);	// get index of acid for simulation of titration curve

		ProjectDialog ();
		virtual ~ProjectDialog ();

	private:

		Gtk::Box* content;
		Gtk::Label title;
		Gtk::Entry project_title;
		Gtk::Label x_funkt;
		Gtk::ComboBoxText func_x;
		Gtk::Button device_x;
		Gtk::Label y_funkt;
		Gtk::ComboBoxText func_y;
		Gtk::Button device_y;
		Gtk::Label comment_label;
		Gtk::ScrolledWindow text_window;
		Gtk::TextView projekt_comment_view;
		Glib::RefPtr<Gtk::TextBuffer> projekt_comment;
		Gtk::Button button_ok;
		Gtk::Button button_cancel;
		Gtk::Label ha_name;
		Gtk::ComboBoxText tit_ha;
		Gtk::Label b_name;
		Gtk::Label ha_conc_label;
		Gtk::Label b_conc_label;
		Gtk::Label havol_label;
		Gtk::Label speed_label;
		Gtk::SpinButton tit_haconc;
		Gtk::SpinButton tit_baseconc;
		Gtk::SpinButton tit_havol;
		Gtk::SpinButton tit_speed;
                Glib::RefPtr<Glib::MainLoop> resp_loop; //loop to pause program until signal response is received
};


class MapFunc : public Gtk::Dialog
{
	public:
		Gtk::Entry	file_function_x;
		Gtk::Entry	file_function_y;
		Gtk::ComboBoxText function_x;
		Gtk::ComboBoxText function_y;

		void translate_functions ();


	MapFunc ();
	virtual ~MapFunc ();

	private:
		Gtk::Box* content;
		Gtk::Label title;
		Gtk::Label x_funkt;
		Gtk::Label y_funkt;
                Glib::RefPtr<Glib::MainLoop> resp_loop; //loop to pause program until signal response is received

		void translate_fkt(int response_id);
};

class MsgDialog : public Gtk::Dialog
{
        public:
                bool dialog_ok (std::string msg);
                void show_msg (std::string msg);

        MsgDialog ();
        virtual ~MsgDialog ();

        private:
                Gtk::Box* content;
                Gtk::Label message;
                Glib::RefPtr<Glib::MainLoop> resp_loop;
                void get_response (int response_id);
                bool dlg_ok;
};


class TimerDialog : public Gtk::Dialog
{
	public:

		void start_mess_with_timer();		//start measurement with timer
		TimerDialog ();
		virtual ~TimerDialog ();

	private:

		Gtk::Box* content;
		Gtk::Label start_label, sec_label;
		Gtk::SpinButton timer_start;
		double timer_cd;	//timer count-down for starting measurement with timer
		sigc::connection countdown_timeout;	//measurement timeout: timeout-handler
		void show_countdown ();
		bool show_countdown_progress ();
		void start_mess_timer (int response_id);
};


class OptionsDialog : public Gtk::Dialog
{
	public:
		Gtk::ColorButton diag_bkcolor;
		Gtk::ColorButton diag_axcolor;
		Gtk::ColorButton diag_gridcolor;
		Gtk::ColorButton diag_xycolor;
		Gtk::ColorButton diag_funktcolor;
		Gtk::Switch diag_gridsw;
		Gtk::Switch diag_autoscalesw;
		Gtk::Switch diag_zerosw;
		Gtk::Switch diag_titlesw;
		Gtk::SpinButton diag_xmin;
		Gtk::SpinButton diag_xmax;
		Gtk::SpinButton diag_ymin;
		Gtk::SpinButton diag_ymax;
		Gtk::SpinButton diag_symw;

		void save_all_options ();
		void load_all_options ();
		void show_options_diag ();	//show options for diagram
		void show_options_device_x ();	//settings for channel X
		void show_options_device_y ();	//settings for channel Y

		OptionsDialog ();
		virtual ~OptionsDialog ();

	private:
		Gtk::Box* content;
		Gtk::Notebook edit_options;
                Glib::RefPtr<Gtk::FileDialog> dmm_file_dialog;
                Glib::RefPtr<Gio::ListStore<Gtk::FileFilter>> dmm_filters;
		Glib::RefPtr<Gtk::FileFilter> filefilter_dmm;
                Glib::RefPtr<Gio::File> dmm_folder;
		Gtk::Label bg_label, ax_label, grid_label, val_label, scale_label;
		Gtk::Label sw_label, sw_auto_label, sw_man_label;
		Gtk::Label xmin_label, xmax_label, ymin_label, ymax_label;
		Gtk::Label zero_label, title_label, src_label, src2_label;
		Gtk::ComboBoxText diag_symbol;
		Gtk::ComboBoxText diag_graph;
		Gtk::ComboBoxText diag_linestyle;
		Gtk::ComboBoxText diag_symbolstyle;
		Gtk::ComboBoxText dmm_typ[2];
		Gtk::ComboBoxText dmm_simtyp[2];
		Gtk::Box dmm_dmm_options[2];
		Gtk::Box dmm_device_options;
		Gtk::Box dmm1_type;
		Gtk::Box dmm2_type;
		Gtk::Box device_type, dev_time;
		Gtk::Label device_label, dev_intface_label, dev_mlabel;
		Gtk::SpinButton dmm_mtime;
		Gtk::Label dmm1_label, intface_label, scpi_label, remote_label;
		Gtk::Label dmm2_label, intface2_label, scpi2_label, remote2_label;
		Gtk::ComboBoxText dmm_name[2];
		Gtk::ComboBoxText device_name;
		Gtk::Button dmm_loadoptions[2];
		Gtk::Button dmm_saveoptions[2];
		Gtk::Box dmm1_connect, dmm2_connect, dev_connect;
		Gtk::ComboBoxText dmm_interface[2], dev_interface;
		Gtk::Switch dmm_scpi[2];
		Gtk::Switch dmm_remote_control[2];
		Gtk::Box dmm_serial_options[2];
		Gtk::Box dmm_usb_options[2];
		Gtk::SpinButton dmm_usb_bytes[2];
		Gtk::Label baud_label, chrsize_label, flow_label, stop_label;
		Gtk::Label par_label, poll_label, nbyte_label, nval_label, timeout_label, ubyte_label;
		Gtk::Label baud2_label, chrsize2_label, flow2_label, stop2_label;
		Gtk::Label par2_label, poll2_label, nbyte2_label, nval2_label, timeout2_label, ubyte2_label;
		Gtk::ComboBoxText dmm_baud[2];
		Gtk::ComboBoxText dmm_bits[2];
		Gtk::ComboBoxText dmm_flowcontrol[2];
		Gtk::ComboBoxText dmm_stopbits[2];
		Gtk::ComboBoxText dmm_parity[2];
		Gtk::Switch dmm_polling[2];
		Gtk::SpinButton dmm_num_bytes[2];
		Gtk::SpinButton dmm_num_val[2];
		Gtk::SpinButton dmm_timeout[2];
		Gtk::Box dmm_function_control[2];
		Gtk::Label dmm1_funkt_label, dmm1_range_label;
		Gtk::Label dmm2_funkt_label, dmm2_range_label;
		Gtk::ComboBoxText dmm_funktion[2];
		Gtk::ComboBoxText dmm_range[2];
		Gtk::Label dmm1_DCV_label, dmm1_ACV_label, dmm1_DCmA_label, dmm1_ACmA_label, dmm1_DCA_label;
		Gtk::Label dmm1_ACA_label, dmm1_res_label, dmm1_cond_label, dmm1_ph_label, dmm1_temp_label;
		Gtk::Label dmm2_DCV_label, dmm2_ACV_label, dmm2_DCmA_label, dmm2_ACmA_label, dmm2_DCA_label;
		Gtk::Label dmm2_ACA_label, dmm2_res_label, dmm2_cond_label, dmm2_ph_label, dmm2_temp_label;
		Gtk::Box dmm_control_options[2];
		Gtk::ComboBoxText dmm_DCV[2];
		Gtk::ComboBoxText dmm_ACV[2];
		Gtk::ComboBoxText dmm_DCmA[2];
		Gtk::ComboBoxText dmm_ACmA[2];
		Gtk::ComboBoxText dmm_DCA[2];
		Gtk::ComboBoxText dmm_ACA[2];
		Gtk::ComboBoxText dmm_Res[2];
		Gtk::ComboBoxText dmm_Cond[2];
		Gtk::ComboBoxText dmm_pH[2];
		Gtk::ComboBoxText dmm_Temp[2];
		Gtk::Box sim_linoptions[2];
		Gtk::Label dmm1_slope_label, dmm1_shift_label;
		Gtk::Label dmm2_slope_label, dmm2_shift_label;
		Gtk::SpinButton sim_slope[2];
		Gtk::SpinButton sim_shift[2];
		Gtk::Label dmm1_autoslope, dmm1_autoshift;
		Gtk::Label dmm2_autoslope, dmm2_autoshift;
		Gtk::Switch sim_slope_switch[2];
		Gtk::Switch sim_shift_switch[2];
		Gtk::Box sim_expoptions;
		Gtk::Box sim_chromoptions;
		Gtk::Label exp_init_label, exp_time_label, exp_shift_label;
		Gtk::Label exp_init_auto, exp_time_auto, exp_shift_auto;
		Gtk::Label chrom_peaks_auto, chrom_peaks_label, chrom_ret_label, chrom_ret_auto;
		Gtk::Label chrom_bf_label, chrom_bf_auto, chrom_drift_label, chrom_drift_auto;
		Gtk::SpinButton sim_init;
		Gtk::SpinButton sim_tc;
		Gtk::SpinButton sim_expshift;
		Gtk::SpinButton sim_np;
		Gtk::SpinButton sim_max_rt;
		Gtk::SpinButton sim_bf;
		Gtk::SpinButton sim_drift;
		Gtk::Switch sim_init_sw;
		Gtk::Switch sim_tc_sw;
		Gtk::Switch sim_expshift_sw;
		Gtk::Switch sim_np_sw;
		Gtk::Switch sim_max_rt_sw;
		Gtk::Switch sim_bf_sw;
		Gtk::Switch sim_drift_sw;
                //save variables to cancel changes
                typ dmm1_typ_saved, dmm2_typ_saved;
                std::string funkt_x_saved;
                Glib::RefPtr<Glib::MainLoop> resp_loop; //loop to pause program until signal response is received



		void set_options();	//set options
		void accept_options (int response_id);
		void set_range_options_device (int k);	//set range options according to function
		void show_diag_settings ();	//show actual settings
		void show_options_Kanal_XY ();
		bool show_diag_manual_limits (bool state);
               	bool show_dmm_control_options (bool state, int kanal);
		void show_dmm_interface_options(int kanal);
		void show_dmm_function_control(int k);
		void show_simulation_options (int k);
		bool show_simlin_options (bool state, int k); // show options for linear simulation
		bool show_simexp_options (bool state); // show options for exponential simulation
		bool show_simchrom_options (bool state); // show options for peak simulation (chromatogram)
		void set_options_diag ();	//set options for diagram
		void set_device_options (int k);	//set options for channel X,Y
		void set_device_options_lutron_ph207 ();
		std::vector<std::string> get_usb_ports ();
		void preset_mtime ();	//preset measuring timeout according to device option
		void set_mtime ();	//set measuring timeout according to device
		void restart_options_x ();
		void restart_options_y ();
		void reset_options_diag ();
		void reset_options_kanal_X ();
		void reset_options_kanal_Y ();
		bool dmm_exist (std::string name);	// seeks name in  array of installed dmms; sets index if found
		void select_dmm (int k);
		void save_dmm_options(int k);
		void save_dmmdata_to_file(const Glib::RefPtr<Gio::AsyncResult>& result, const Glib::RefPtr<Gtk::FileDialog>& dmm_file_dialog);
		void load_dmm_options(int k);
		void read_dmmdata_from_file(const Glib::RefPtr<Gio::AsyncResult>& result, const Glib::RefPtr<Gtk::FileDialog>& dmm_file_dialog);
		std::string read_option(std::string opt_item);
		std::string read_dmmoption(std::string opt_item);
                void set_simtyp ();

};


class EvalData_Transform_Dialog : public Gtk::Window
{
        public:

		EvalData_Transform_Dialog ();
                Gtk::ComboBoxText evaloption_xtherm;
		Gtk::ComboBoxText evaloption_ytherm;
		Gtk::SpinButton evaloption_volspeed;
                Gtk::Switch evaloption_vol;
		Gtk::Switch evaloption_xreziproksw;
		Gtk::Switch evaloption_yreziproksw;
		Gtk::Switch evaloption_xlogsw;
		Gtk::Switch evaloption_ylogsw;
                Glib::RefPtr<Glib::MainLoop> resp_loop; //loop to pause program until signal response is received
                void reset_data_transformation ();

		virtual ~EvalData_Transform_Dialog ();

        private:
                Gtk::Box content;
                Gtk::Box button_box;
                Gtk::Button button_ok, button_cancel, button_reset;
                Gtk::Label x_label, titvol_label, xtherm_label, xinv_label, xlog_label;
		Gtk::Label y_label, ytherm_label, yinv_label, ylog_label;

                bool show_eval_volspeed (bool state); //set volspeed sensitive if time->vol
                void cancel_data_transformation ();

};

class Eval_Function_Dialog : public Gtk::Window
{
        public:

		Eval_Function_Dialog ();
                Gtk::ColorButton diag_funktcolor;
		Gtk::Box integration_options;
                Gtk::SpinButton evaloption_minpeakscale;
		Gtk::SpinButton evaloption_mindiffscale;
                Gtk::Switch evaloption_reglin;
		Gtk::Switch evaloption_integration;
		Gtk::Switch evaloption_diff;
		Gtk::Switch evaloption_show_baseline;
		Gtk::Switch evaloption_show_peakarea;
		Gtk::Switch evaloption_show_peaklimits;
                Glib::RefPtr<Glib::MainLoop> resp_loop; //loop to pause program until signal response is received

                bool show_mindiffscale (bool state); // set minimum scale for differential quotient
                bool show_evaloptions_integration (bool state); //set options for peak integration
                void reset_eval_functions ();
                void do_reset_eval_functions ();


		virtual ~Eval_Function_Dialog ();

        private:
                Gtk::Box content;
                Gtk::Box button_box;
                Gtk::Button button_ok, button_cancel, button_reset;
                Gtk::Label fgraph_label, reglin_label, evaldiff_min_label, peakint_label, int_min_label;
		Gtk::Label bline_label, limits_label, area_label, diff_label;

                void cancel_eval_functions ();

};


class EvalResults : public Gtk::Window
{
	public:
		EvalResults ();
                Pango::TabArray tabs;
                Gtk::TextView eval_results_view;
		Gtk::Label eval_funktion;
                Glib::RefPtr<Gtk::TextBuffer> eval_result_items;	//results of evaluation

		virtual ~EvalResults ();


	private:
		Gtk::Box content;
                Gtk::Button button_close;

                void close_results ();
};

class Print_Dialog : public Gtk::Window
{
        public:
                Print_Dialog ();
                Glib::RefPtr<Gtk::PrintSettings> print_settings;
                Gtk::ComboBoxText page_orientation;

                //Page Elements to print
                bool printoption_title = true;
		bool printoption_comment = true;
		bool printoption_diag = true;
		bool printoption_result = true;

                //Page layout: document margins in mm (user input)
                double top_margin, bottom_margin, left_margin, right_margin;

                Gtk::PrintOperation::Action print_action;
                Gtk::Switch titlesw, commentsw, diagsw, resultsw;
                Gtk::SpinButton lm, rm, tm, bm;

                void prepare_printreport ();
                void cancel_printreport ();
                void show_printoptions();
                void set_printoptions();
                void print_report ();
                void save_print_settings (Gtk::PrintOperation::Result result);
                void print_operation_status ();

                virtual ~Print_Dialog ();

        private:
                PrintOP *print_op;
                Gtk::Box print_options;
                Gtk::Box pr_box, elem_box, mrg_box;
                Gtk::Box title_box, comment_box, diagram_box, result_box, layout_box, format_box;
                Gtk::Box left_box, right_box, top_box, bottom_box;
                Gtk::Box orient_box;
                Gtk::Box button_box;
                Gtk::Button button_print, button_cancel, button_preview;
                Gtk::Label title, comment, diagram, result;
                Gtk::Label l_margin, r_margin, t_margin, b_margin, unit, unit_str;
                Gtk::Label section_elements, section_margin, section_format;
                Gtk::Label orient;
};


class Main_Window : public Gtk::ApplicationWindow
{
	public:
		//variables
		//menu
		Glib::RefPtr<Gio::Menu> menu;	//main menu
		Glib::RefPtr<Gio::Menu> menu_file; //submenu
		Glib::RefPtr<Gio::Menu> menu_export; //submenu
		Glib::RefPtr<Gio::Menu> menu_view; //submenu
		Glib::RefPtr<Gio::Menu> menu_mess;	//submenu
		Glib::RefPtr<Gio::Menu> menu_eval; //submenu
		Glib::RefPtr<Gio::Menu> menu_options; //submenu
		Glib::RefPtr<Gio::Menu> menu_options_auto; //submenu
		Glib::RefPtr<Gio::Menu> menu_help; //submenu

		//actions
		Glib::RefPtr<Gio::SimpleAction> action_new;
		Glib::RefPtr<Gio::SimpleAction> action_open;
		Glib::RefPtr<Gio::SimpleAction> action_save;
		Glib::RefPtr<Gio::SimpleAction> action_print;
		Glib::RefPtr<Gio::SimpleAction> action_export;
		Glib::RefPtr<Gio::SimpleAction> display_toggle;
		Glib::RefPtr<Gio::SimpleAction> action_mess_new;
		Glib::RefPtr<Gio::SimpleAction> action_mess_start;
		Glib::RefPtr<Gio::SimpleAction> action_mess_start_with_timer;
		Glib::RefPtr<Gio::SimpleAction> action_mess_cancel;
		Glib::RefPtr<Gio::SimpleAction> action_mess_stop;
		Glib::RefPtr<Gio::SimpleAction> action_mess_end;
		Glib::RefPtr<Gio::SimpleAction> action_transform_data;
                Glib::RefPtr<Gio::SimpleAction> action_eval_functions;
		Glib::RefPtr<Gio::SimpleAction> toggle_autosave;
		Glib::RefPtr<Gio::SimpleAction> toggle_autoload;
		Glib::RefPtr<Gio::SimpleAction> action_options_device_x;
		Glib::RefPtr<Gio::SimpleAction> action_options_device_y;
		Glib::RefPtr<Gio::SimpleAction> action_options_diag;

		Gtk::Box toolbar;
		Gtk::Box main_box;
		Gtk::Button button_new;
		Gtk::Button button_edit;
		Gtk::Button button_open;
		Gtk::Button button_save;
		Gtk::Button button_export;
		Gtk::Button button_print;
		Gtk::Button button_mess;
		Gtk::Button button_start;
		Gtk::Button button_timer;
		Gtk::Button button_cancel;
		Gtk::Button button_stop;
		Gtk::Button button_reset;
		Gtk::Button button_reset_scale;
		Gtk::Label count_down_start;
		Gtk::ProgressBar count_down_progress;
		Gtk::AspectFrame frame_x;
		Gtk::Label display_x;
		Gtk::AspectFrame frame_y;
		Gtk::Label display_y;
                Gtk::Label status_info;

		Diagramm diag;

		// Dialogs
		ProjectDialog* projekt_prop;	//project settings
		Gtk::MessageDialog* error_dialog;
                Glib::RefPtr<Gtk::AlertDialog> info_dialog;
		MsgDialog* msg_dialog;
                Glib::RefPtr<Gtk::FileDialog> file_dialog;
		Glib::RefPtr<Gtk::FileFilter> filefilter_dat;
		Glib::RefPtr<Gtk::FileFilter> filefilter_img;
  		MapFunc* map_func;
		OptionsDialog* options_dialog;
		TimerDialog* timer_dialog;
		EvalData_Transform_Dialog* data_transform_dialog;
                Eval_Function_Dialog* eval_function_dialog;
		EvalResults* eval_results;
                Print_Dialog* print_dialog;

		bool show_display;
		bool autosave;
		bool autoload;

		//functions
		void toggle_display ();	//set status of display for measured values
		void set_autoload (); //set status for autoload settings
		void set_autosave (); //set status for autosave settings
		void about (); //show infos about galvani
		void help (); //show manual
                void info (std::string msg); //show info

		Main_Window();
		virtual ~Main_Window();

	private:
		Gtk::AboutDialog* about_dialog;
		Gtk::Window help_browser;
                Glib::RefPtr<Gio::File> docfile;
                Gio::SlotAsyncReady slot;
		Glib::RefPtr<Gio::Cancellable> cancel;

};



//Functions used in menu and toolbar

void open_datafile(); //open data file
void save_data();	//save data
void app_quit();	//quit program
void export_diag();	//export diagram
void begin_mess(); //new measurement
void cancel_mess();		//cancel measurement
void start_mess(); //start measurement
void stop_mess(); //stop measurement
void end_mess(); //end measurement and rearrange
void error_msg (std::string msg); //error message


#endif

