#	This file is part of do228
#
#	The do228 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.
#
#	The do228 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 do228.  If not, see <http://www.gnu.org/licenses/>.
#
#	Dornier DO228 simulation by Benedikt Wolf (D-ECHO)
#	Started 06/2020

###################################################
##		Universal RCU simulation
##	by Benedikt Wolf (D-ECHO) 2020-2023
##	based on
##		A3XX Lower ECAM Canvas by Joshua Davidson (Octal450)
##	References:	http://www.uasc.com/home/shop/avionics/rcu
##			http://www.uasc.com/docs/default-source/documents/brochures/uasc_rcu_brochure.pdf?sfvrsn=6a13985c_4

var instrument_path = "Aircraft/do228/Models/Instruments/RCU/";

var rcu_main = nil;
var rcu_display = nil;

var volts	=	props.globals.getNode("systems/electrical/outputs/rcu[0]");

#	Instrument Properties

#	RCU
var rcu = props.globals.initNode("instrumentation/rcu[0]");
var cross_tune = rcu.initNode("cross-tune", 0, "BOOL");
#	Active Selection:
#		0 = none
#		1 = L1 (COM Preset)
#		2 = L2 (NAV Preset)
#		3 = L3 (ADF Preset)
#		4 = L4 (ATC Mode)
#		5 = R1 (COM Sel)
#		6 = R2 (NAV Sel)
#		7 = R3 (ADF Sel)
#		8 = R4 (ATC Sel)
#		9 = C1 (COM ACTIVE)
#		10 = C2 (NAV ACTIVE)
#		11 = C3 (ADF ACTIVE)
#		12 = C4 (ATC ACTIVE)
var selection_act = rcu.initNode("active-selection", 0, "INT");

#	COM
var com = [ nil, nil ];
com[0] = {
	freq_sel:	props.globals.getNode("instrumentation/comm[0]/frequencies/selected-mhz"),
	freq_sby:	props.globals.getNode("instrumentation/comm[0]/frequencies/standby-mhz"),
};
com[1] = {
	freq_sel:	props.globals.getNode("instrumentation/comm[1]/frequencies/selected-mhz"),
	freq_sby:	props.globals.getNode("instrumentation/comm[1]/frequencies/standby-mhz"),
};

#	NAV
var nav = [ nil, nil ];
nav[0] = {
	freq_sel:	props.globals.getNode("instrumentation/nav[0]/frequencies/selected-mhz"),
	freq_sby:	props.globals.getNode("instrumentation/nav[0]/frequencies/standby-mhz"),
};
nav[1] = {
	freq_sel:	props.globals.getNode("instrumentation/nav[1]/frequencies/selected-mhz"),
	freq_sby:	props.globals.getNode("instrumentation/nav[1]/frequencies/standby-mhz"),
};

#	ADF
var adf = [ nil, nil ];
adf[0] = {
	freq_sel: 	props.globals.getNode("instrumentation/adf[0]/frequencies/selected-khz"),
	freq_sby: 	props.globals.getNode("instrumentation/adf[0]/frequencies/standby-khz"),
};
adf[1] = {
	freq_sel: 	props.globals.getNode("instrumentation/adf[1]/frequencies/selected-khz"),
	freq_sby: 	props.globals.getNode("instrumentation/adf[1]/frequencies/standby-khz"),
};

#	ATC
var atc = [ nil, nil ];
atc[0] = {
	mode:		props.globals.getNode("instrumentation/transponder[0]/inputs/knob-mode"),
	code:		props.globals.getNode("instrumentation/transponder[0]/id-code"),
	code_sby:	props.globals.initNode("instrumentation/transponder[0]/inputs/id-code-standby", 0, "INT"),
	reply:		props.globals.initNode("instrumentation/transponder[0]/reply-flag", 0, "BOOL"),	# TODO
};
atc[1] = {
	mode:		props.globals.getNode("instrumentation/transponder[0]/inputs/knob-mode"),
	code:		props.globals.getNode("instrumentation/transponder[0]/id-code"),
	reply:		props.globals.initNode("instrumentation/transponder[0]/reply-flag", 0, "BOOL"),	# TODO
};
var atc_modes = [ "OFF", "STBY", "--", "--", "ON", "ALT" ];

var canvas_RCU_base = {
	init: func(canvas_group, file) {
		var font_mapper = func(family, weight) {
			return "LiberationFonts/LiberationMono-Regular.ttf";
		};

		canvas.parsesvg(canvas_group, file, {'font-mapper': font_mapper});
		
		var svg_keys = me.getKeys();
				
		foreach(var key; svg_keys) {
			me[key] = canvas_group.getElementById(key);
			var svg_keys = me.getKeys();
			foreach (var key; svg_keys) {
			me[key] = canvas_group.getElementById(key);
			var clip_el = canvas_group.getElementById(key ~ "_clip");
			if (clip_el != nil) {
				clip_el.setVisible(0);
				var tran_rect = clip_el.getTransformedBounds();
				var clip_rect = sprintf("rect(%d,%d, %d,%d)", 
				tran_rect[1], # 0 ys
				tran_rect[2], # 1 xe
				tran_rect[3], # 2 ye
				tran_rect[0]); #3 xs
				#   coordinates are top,right,bottom,left (ys, xe, ye, xs) ref: l621 of simgear/canvas/CanvasElement.cxx
				me[key].set("clip", clip_rect);
				me[key].set("clip-frame", canvas.Element.PARENT);
			}
			}
		}
		
		me.page = canvas_group;

		return me;
	},
	getKeys: func() {
		return [];
	},
	update: func() {
		if (volts.getDoubleValue() ) {
			rcu_main.page.show();
			rcu_main.update();
		} else {
			rcu_main.page.hide();
		}
	},
};

var old_active = -1;

var canvas_RCU_main = {
	new: func(canvas_group, file) {
		var m = { parents: [canvas_RCU_main, canvas_RCU_base] };
		m.init(canvas_group, file);

		return m;
	},
	getKeys: func() {
		return ["active.L1","active.L2","active.L3","active.L4","active.R1","active.R2","active.R3","active.R4","active.C1","active.C2","active.C3","active.C4",
			"com.freq", "com.sel.freq", "com.sel.station",
			"nav.freq", "nav.sel.freq", "nav.sel.station",
			"adf.freq", "adf.sel.freq", "adf.sel.station",
			"atc.mode", "atc.code", "atc.reply_flag", "atc.sel.code"];
	},
	update: func() {
		
		# Active Field box
		var active = selection_act.getIntValue();
		if( active != old_active ) {
			if( active == 0 ){
				me["active.L1"].hide();
				me["active.L2"].hide();
				me["active.L3"].hide();
				me["active.L4"].hide();
				me["active.R1"].hide();
				me["active.R2"].hide();
				me["active.R3"].hide();
				me["active.R4"].hide();
				me["active.C1"].hide();
				me["active.C2"].hide();
				me["active.C3"].hide();
				me["active.C4"].hide();
			} else if ( active == 1 ){
				me["active.L1"].show();
				me["active.L2"].hide();
				me["active.L3"].hide();
				me["active.L4"].hide();
				me["active.R1"].hide();
				me["active.R2"].hide();
				me["active.R3"].hide();
				me["active.R4"].hide();
				me["active.C1"].hide();
				me["active.C2"].hide();
				me["active.C3"].hide();
				me["active.C4"].hide();
			} else if ( active == 2 ){
				me["active.L1"].hide();
				me["active.L2"].show();
				me["active.L3"].hide();
				me["active.L4"].hide();
				me["active.R1"].hide();
				me["active.R2"].hide();
				me["active.R3"].hide();
				me["active.R4"].hide();
				me["active.C1"].hide();
				me["active.C2"].hide();
				me["active.C3"].hide();
				me["active.C4"].hide();
			} else if ( active == 3 ){
				me["active.L1"].hide();
				me["active.L2"].hide();
				me["active.L3"].show();
				me["active.L4"].hide();
				me["active.R1"].hide();
				me["active.R2"].hide();
				me["active.R3"].hide();
				me["active.R4"].hide();
				me["active.C1"].hide();
				me["active.C2"].hide();
				me["active.C3"].hide();
				me["active.C4"].hide();
			} else if ( active == 4 ){
				me["active.L1"].hide();
				me["active.L2"].hide();
				me["active.L3"].hide();
				me["active.L4"].show();
				me["active.R1"].hide();
				me["active.R2"].hide();
				me["active.R3"].hide();
				me["active.R4"].hide();
				me["active.C1"].hide();
				me["active.C2"].hide();
				me["active.C3"].hide();
				me["active.C4"].hide();
			} else if ( active == 5 ){
				me["active.L1"].hide();
				me["active.L2"].hide();
				me["active.L3"].hide();
				me["active.L4"].hide();
				me["active.R1"].show();
				me["active.R2"].hide();
				me["active.R3"].hide();
				me["active.R4"].hide();
				me["active.C1"].hide();
				me["active.C2"].hide();
				me["active.C3"].hide();
				me["active.C4"].hide();
			} else if ( active == 6 ){
				me["active.L1"].hide();
				me["active.L2"].hide();
				me["active.L3"].hide();
				me["active.L4"].hide();
				me["active.R1"].hide();
				me["active.R2"].show();
				me["active.R3"].hide();
				me["active.R4"].hide();
				me["active.C1"].hide();
				me["active.C2"].hide();
				me["active.C3"].hide();
				me["active.C4"].hide();
			} else if ( active == 7 ){
				me["active.L1"].hide();
				me["active.L2"].hide();
				me["active.L3"].hide();
				me["active.L4"].hide();
				me["active.R1"].hide();
				me["active.R2"].hide();
				me["active.R3"].show();
				me["active.R4"].hide();
				me["active.C1"].hide();
				me["active.C2"].hide();
				me["active.C3"].hide();
				me["active.C4"].hide();
			} else if ( active == 8 ){
				me["active.L1"].hide();
				me["active.L2"].hide();
				me["active.L3"].hide();
				me["active.L4"].hide();
				me["active.R1"].hide();
				me["active.R2"].hide();
				me["active.R3"].hide();
				me["active.R4"].show();
				me["active.C1"].hide();
				me["active.C2"].hide();
				me["active.C3"].hide();
				me["active.C4"].hide();
			} else if ( active == 9 ){
				me["active.L1"].hide();
				me["active.L2"].hide();
				me["active.L3"].hide();
				me["active.L4"].hide();
				me["active.R1"].hide();
				me["active.R2"].hide();
				me["active.R3"].hide();
				me["active.R4"].hide();
				me["active.C1"].show();
				me["active.C2"].hide();
				me["active.C3"].hide();
				me["active.C4"].hide();
			} else if ( active == 10 ){
				me["active.L1"].hide();
				me["active.L2"].hide();
				me["active.L3"].hide();
				me["active.L4"].hide();
				me["active.R1"].hide();
				me["active.R2"].hide();
				me["active.R3"].hide();
				me["active.R4"].hide();
				me["active.C1"].hide();
				me["active.C2"].show();
				me["active.C3"].hide();
				me["active.C4"].hide();
			} else if ( active == 11 ){
				me["active.L1"].hide();
				me["active.L2"].hide();
				me["active.L3"].hide();
				me["active.L4"].hide();
				me["active.R1"].hide();
				me["active.R2"].hide();
				me["active.R3"].hide();
				me["active.R4"].hide();
				me["active.C1"].hide();
				me["active.C2"].hide();
				me["active.C3"].show();
				me["active.C4"].hide();
			} else if ( active == 12 ){
				me["active.L1"].hide();
				me["active.L2"].hide();
				me["active.L3"].hide();
				me["active.L4"].hide();
				me["active.R1"].hide();
				me["active.R2"].hide();
				me["active.R3"].hide();
				me["active.R4"].hide();
				me["active.C1"].hide();
				me["active.C2"].hide();
				me["active.C3"].hide();
				me["active.C4"].show();
			} else {
				print( "RCU: Unknown active selection!");
			}
			old_active = active;
		}
		
		# COM
		me["com.freq"].setText( sprintf("%6.3f", com[0].freq_sel.getDoubleValue() ) );
		me["com.sel.freq"].setText( sprintf("%6.3f", com[0].freq_sby.getDoubleValue() ) );
		
		# NAV
		me["nav.freq"].setText( sprintf("%5.2f", nav[0].freq_sel.getDoubleValue() ) );
		me["nav.sel.freq"].setText( sprintf("%5.2f", nav[0].freq_sby.getDoubleValue() ) );
		
		# ADF
		me["adf.freq"].setText( sprintf("%4.1f", adf[0].freq_sel.getIntValue() ) );
		me["adf.sel.freq"].setText( sprintf("%4.1f", adf[0].freq_sby.getIntValue() ) );
		
		# ATC
		me["atc.mode"].setText( atc_modes[ atc[0].mode.getIntValue() ] );
		me["atc.code"].setText( sprintf("%04d", atc[0].code.getIntValue() ) );
		me["atc.reply_flag"].setVisible( atc[0].reply.getBoolValue() );
		me["atc.sel.code"].setText( sprintf("%04d", atc[0].code_sby.getIntValue() ) );
	},
};

var rcu_update = maketimer( 0.2, func { canvas_RCU_base.update(); } );
rcu_update.simulatedTime = 1;

var ls = setlistener("sim/signals/fdm-initialized", func {
	RCU_display = canvas.new({
		"name": "RCU",
		"size": [504, 264],
		"view": [504, 264],
		"mipmapping": 1
	});
	RCU_display.addPlacement({"node": "rcu.display"});
	var groupRCUmain = RCU_display.createGroup();
	
	rcu_main = canvas_RCU_main.new(groupRCUmain, instrument_path~"rcu_main.svg");
	
	rcu_update.start();
	
	removelistener( ls );
});

# Automatically reset active selection to 0 (none) after 15 seconds ( TODO reference needed )
setlistener( selection_act, func {
	if( selection_act.getIntValue() != 0 ){
		settimer( func { selection_act.setIntValue( 0 ) }, 15 );
	}
});
