# Properties under /consumables/fuel/tank[n]:
# + level-gal_us    - Current fuel load.  Can be set by user code.
# + level-lbs       - OUTPUT ONLY property, do not try to set
# + selected        - boolean indicating tank selection.
# + density-ppg     - Fuel density, in lbs/gallon.
# + capacity-gal_us - Tank capacity
#
# Properties under /engines/engine[n]:
# + fuel-consumed-lbs - Output from the FDM, zeroed by this script
# + out-of-fuel       - boolean, set by this code.


var UPDATE_PERIOD = 0.3;


update = func {
	if (fuel_freeze) {
		return;
	}

	var consumed_fuel = 0;
	foreach (var e; engines) {
		var fuel = e.getNode("fuel-consumed-lbs");
		consumed_fuel += fuel.getValue();
		fuel.setDoubleValue(0);
	}

	if (!consumed_fuel) {
		return;
	}

	var selected_tanks = [];
	foreach (var t; tanks) {
		var cap = t.getNode("capacity-gal_us").getValue();
		if (cap > 0.01 and t.getNode("selected").getBoolValue()) {
			append(selected_tanks, t);
		}
	}

	# Subtract fuel from tanks, set auxilliary properties.  Set out-of-fuel
	# when any one tank is dry.
	var out_of_fuel = 0;
	if (size(selected_tanks) == 0) {
		out_of_fuel = 1;
	} else {
		var fuel_per_tank = consumed_fuel / size(selected_tanks);
		foreach (var t; selected_tanks) {
			var ppg = t.getNode("density-ppg").getValue();
			var lbs = t.getNode("level-gal_us").getValue() * ppg;
			lbs = lbs - fuel_per_tank;
			if (lbs < 0) {
				lbs = 0;
				# Kill the engines if we're told to, otherwise simply
				# deselect the tank.
				if (t.getNode("kill-when-empty", 1).getBoolValue()) {
					out_of_fuel = 1;
				} else {
					t.getNode("selected").setBoolValue(0);
				}
			}
			var gals = lbs / ppg;
			t.getNode("level-gal_us").setDoubleValue(gals);
			t.getNode("level-lbs").setDoubleValue(lbs);
		}
	}

	# Total fuel properties
	var lbs = 0;
	var gals = 0;
	var cap = 0;

	foreach (var t; tanks) {
		lbs += t.getNode("level-lbs").getValue();
		gals += t.getNode("level-gal_us").getValue();
		cap += t.getNode("capacity-gal_us").getValue();
	}

	total_lbs.setDoubleValue(lbs);
	total_gals.setDoubleValue(gals);
	total_norm.setDoubleValue(gals / cap);

	foreach (var e; engines) {
		e.getNode("out-of-fuel").setBoolValue(out_of_fuel);
	}
}


loop = func {
	update();
	settimer(loop, UPDATE_PERIOD);
}


init_double_prop = func(node, prop, val) {
	if (node.getNode(prop) != nil) {
		val = num(node.getNode(prop).getValue());
	}
	node.getNode(prop, 1).setDoubleValue(val);
}



var tanks = [];
var engines = [];
var fuel_freeze = nil;
var total_gals = nil;
var total_lbs = nil;
var total_norm = nil;


var L = _setlistener("/sim/signals/fdm-initialized", func {
	removelistener(L);

	setlistener("/sim/freeze/fuel", func { fuel_freeze = cmdarg().getBoolValue() }, 1);

	total_gals = props.globals.getNode("/consumables/fuel/total-fuel-gals", 1);
	total_lbs = props.globals.getNode("/consumables/fuel/total-fuel-lbs", 1);
	total_norm = props.globals.getNode("/consumables/fuel/total-fuel-norm", 1);

	engines = props.globals.getNode("engines", 1).getChildren("engine");
	foreach (var e; engines) {
		e.getNode("fuel-consumed-lbs", 1).setDoubleValue(0);
		e.getNode("out-of-fuel", 1).setBoolValue(0);
	}

	foreach (var t; props.globals.getNode("/consumables/fuel", 1).getChildren("tank")) {
		if (!size(t.getChildren())) {
			continue;           # skip native_fdm.cxx generated zombie tanks
		}
		append(tanks, t);
		init_double_prop(t, "level-gal_us", 0.0);
		init_double_prop(t, "level-lbs", 0.0);
		init_double_prop(t, "capacity-gal_us", 0.01); # not zero (div/zero issue)
		init_double_prop(t, "density-ppg", 6.0);      # gasoline

		if (t.getNode("selected") == nil) {
			t.getNode("selected", 1).setBoolValue(1);
		}
	}

	loop();
});