# ===============================================================
#                   Air and Terrain Mode Radar
#                    for Nord N.262E Fregate
#                     AMOROSO Paolo 05/2025
#
#               Updated : BARANGER Emmanuel 06/2025
# ===============================================================
MPjoin = func(n) {
  var base = n.getValue();
  setprop("instrumentation/radar/" ~ base ~ "/radar/y-shift", 0);
  setprop("instrumentation/radar/" ~ base ~ "/radar/x-shift", 0);
  setprop("instrumentation/radar/" ~ base ~ "/radar/rotation", 0);
  setprop("instrumentation/radar/" ~ base ~ "/radar/in-range", 0);
  setprop("instrumentation/radar/" ~ base ~ "/radar/h-offset", 180);
  setprop("instrumentation/radar/" ~ base ~ "/joined", 1);
}

MPleave = func(n) {
  var base = n.getValue();
  setprop("instrumentation/radar/" ~ base ~ "/radar/in-range", 0);
  setprop("instrumentation/radar/" ~ base ~ "/joined", 0);
}

MPradarProperties = func {
  var targetList = props.globals.getNode("ai/models/").getChildren("multiplayer");
  foreach (d; props.globals.getNode("ai/models/").getChildren("aircraft")) {
    append(targetList, d);
  }

  foreach (m; targetList) {
    var name  = m.getName();
    var index = m.getIndex();
    var path  = "instrumentation/radar/ai/models/" ~ name ~ "[" ~ index ~ "]/";
    var sourcePath = "ai/models/" ~ name ~ "[" ~ index ~ "]/";

    if (getprop(path ~ "joined") == 1 or name == "aircraft") {
      var factor = getprop("instrumentation/radar/range-factor");
      if (factor == nil) {
        factor = 1.0;
      }

      var yNode       = m.getNode("radar/y-shift", 0);
      var xNode       = m.getNode("radar/x-shift", 0);
      var rotNode     = m.getNode("radar/rotation", 0);
      var hOffNode    = m.getNode("radar/h-offset", 0);
      var inRangeNode = m.getNode("radar/in-range", 0);

      var yVal        = yNode != nil and yNode.getValue() != nil ? yNode.getValue() : 0;
      var xVal        = xNode != nil and xNode.getValue() != nil ? xNode.getValue() : 0;
      var rotVal      = rotNode != nil and rotNode.getValue() != nil ? rotNode.getValue() : 0;
      var hOffVal     = hOffNode != nil and hOffNode.getValue() != nil ? hOffNode.getValue() : 0;
      var inRangeVal  = inRangeNode != nil and inRangeNode.getValue() != nil ? inRangeNode.getValue() : 0;

      setprop(path ~ "radar/y-shift", yVal * factor);
      setprop(path ~ "radar/x-shift", xVal * factor);
      setprop(path ~ "radar/rotation", rotVal);
      setprop(path ~ "radar/h-offset", hOffVal);

      if (getprop("instrumentation/radar/selected") == 2) {
        var xShift = getprop(path ~ "radar/x-shift");
        if (xShift < -0.04 or xShift > 0.04) {
          setprop(path ~ "radar/in-range", 0);
        } else {
          setprop(path ~ "radar/in-range", inRangeVal);
        }
      } else {
        setprop(path ~ "radar/in-range", inRangeVal);
      }
    }
  }

  var selected = getprop("instrumentation/radar/selected");
  var range    = getprop("instrumentation/radar/range");

  # Range Scaling Factor
  if (selected == 2) {
    if (range == 10) {
      setprop("instrumentation/radar/range", 20);
      setprop("instrumentation/radar/range-factor", 0.002);
    } elsif (range == 20) {
      setprop("instrumentation/radar/range-factor", 0.003246);
    } else {
      setprop("instrumentation/radar/range-factor", 0.001623);
    }
  } elsif (selected == 3 or selected == 4) {
    if (range == 40) {
      setprop("instrumentation/radar/range", 20);
      setprop("instrumentation/radar/range-factor", 0.001888);
    } elsif (range == 20) {
      setprop("instrumentation/radar/range-factor", 0.001888);
    } else {
      setprop("instrumentation/radar/range-factor", 0.003776);
    }
  }
  settimer(MPradarProperties, 0.05);
}

# =====================
#  Boresight Detecting
# =====================
locking = 0;
found   = -1;

boreSightLock = func {
  if (getprop("instrumentation/radar/selected") == 1) {
    targetList= props.globals.getNode("ai/models/").getChildren("multiplayer");

    foreach (d; props.globals.getNode("ai/models/").getChildren("aircraft")) {
      append(targetList,d);
    }

    foreach (m; targetList) {
      var string  = "instrumentation/radar/ai/models/"~m.getName()~"["~m.getIndex()~"]";
      var string1 = "ai/models/"~m.getName()~"["~m.getIndex()~"]";
      if (getprop(string1~"radar/in-range")) {

        hOffset = getprop(string1~"radar/h-offset");
        vOffset = getprop(string1~"radar/v-offset");

        #really should be a cone, but is a square pyramid to avoid trigonemetry
        if(hOffset < 3 and hOffset > -3 and vOffset < 3 and vOffset > -3) {
          if (locking == 11) {
            setprop(string~"radar/boreLock",2);
            setprop("instrumentation/radar/lock",2);
            setprop("sim[0]/hud/current-color",1);
            locking -= 1;
          } elsif (locking ==1 or locking ==3 or locking ==5 or locking ==7 or locking ==9 ) {
            setprop("instrumentation/radar/lock",1);
            setprop(string1~"radar/boreLock",1);
          } else {
            setprop("instrumentation/radar/lock",0);
            setprop(string~"radar/boreLock",1);
          }

          if (found != m.getIndex()) {
            found   = m.getIndex();
            locking = 0;
          } else {
            locking += 1;
          }
          settimer(boreSightLock, 0.2);
          return;
        }
      }
    }
    setprop(string~"radar/boreLock",0);
    locking = 0;
    setprop("sim[0]/hud/current-color",0);
  }

  locking = 0;
  setprop("sim[0]/hud/current-color",0);
  found   = -1;
  setprop("instrumentation/radar/lock",0);

  settimer(boreSightLock, 0.2);
}

setlistener("ai/models/model-added", MPjoin);
setlistener("ai/models/model-removed", MPleave);
settimer(MPradarProperties,1.0);
settimer(boreSightLock, 1.0);

# ==============================
#  Terrain Clearance Radar Mode
# ==============================

#                                              3D radar line length in meters
var DISP_LENGTH   = 0.0856;
#                                              fixed number of plots
var DISP_DEF      = 100;
#                                              vertical calibration
var DEV_CALIB     = 1.5;
#                                              radar update every 0.5s
var UPDATE_PERIOD = 0.5;

var ac_lat        = props.globals.getNode("/position/latitude-deg");
var ac_lon        = props.globals.getNode("/position/longitude-deg");
var ac_alt        = props.globals.getNode("/position/altitude-ft");
var ac_hdg        = props.globals.getNode("/orientation/heading-deg");

var FT2M          = 0.3048;
var NM2M          = 1852;
var D2R           = math.pi / 180;

#                                              radar range 5 NM
var MAX_RANGE_M   = 5 * NM2M;
#                                              5 NM per 100 plots
var interval_m    = MAX_RANGE_M / DISP_DEF;
var radar_scale   = DISP_LENGTH / MAX_RANGE_M;

# Main update function
var update_radar = func {
  var lat   = ac_lat.getValue();
  var lon   = ac_lon.getValue();
  var hdg   = ac_hdg.getValue();
  var own   = geo.Coord.new().set_latlon(lat, lon);
  var alt_m = ac_alt.getValue() * FT2M;

  for (var i = 0; i < DISP_DEF; i += 1) {
    var d     = i * interval_m;
    var coord = own.apply_course_distance(hdg, d);
    var elev  = geo.elevation(coord.lat(), coord.lon()) or 0;

    var dev = (elev - alt_m) * radar_scale * DEV_CALIB;
    var s   = props.globals.getNode("/sim/model/instrumentation/RADAR/s[" ~ i ~ "]", 1);
    s.getNode("elevation_m", 1).setDoubleValue(dev);
    s.getNode("visible", 1).setBoolValue(1);
  }
}

# Loop
var radar_loop = func {
  update_radar();
  settimer(radar_loop, UPDATE_PERIOD);
}

# Initialisation
var RADAR_init = func {
  print("Radar updated");
  radar_loop();
}

RADAR_init();
