///|
pub(all) struct LiveSetObservation {
  response_text : String
  observed_set_usage_ms : Int?
  observed_summary : @dcp.DeviceSummary?
} derive(Eq)

///|
fn root_facade_native_handoff_text(
  api_symbol : String,
  legacy_surface : String,
  fields : Array[String],
) -> String {
  let lines : Array[String] = []
  lines.push("provider_harness_handoff=true")
  lines.push("provider=profinet_master")
  lines.push("handoff_scope=root_facade_native")
  lines.push("api_symbol=" + api_symbol)
  lines.push("protocol_stage=DCP")
  lines.push("legacy_surface=" + legacy_surface)
  lines.push(
    "provider_harness_entry=fieldbus_core/profinet_master_harness/profinet_root_facade_native_handoffs",
  )
  lines.push(
    "required_binding_id=profinet.rawnet.windows_npcap.to_lockwire_session|profinet.rawnet.linux_af_packet.to_lockwire_session",
  )
  lines.push("required_driver_id=profinet.rawnet.raw_ethernet")
  lines.push("lockwire_dependency_in_profinet=false")
  lines.push("fieldbus_core_dependency_in_profinet=false")
  lines.push("live_open_default_allowed=false")
  lines.push("live_open_attempted=false")
  lines.push("native_result_materialized=false")
  for field in fields {
    lines.push(field)
  }
  lines.join("\n")
}

///|
fn format_live_set_observation(observation : LiveSetObservation) -> String {
  let lines : Array[String] = []
  lines.push("response_text_begin")
  lines.push(observation.response_text)
  lines.push("response_text_end")
  let observed_set_usage_ms = match observation.observed_set_usage_ms {
    Some(value) => value.to_string()
    None => ""
  }
  lines.push("observed_set_usage_time_ms=" + observed_set_usage_ms)
  lines.push(
    "target_state_observed=" +
    (observation.observed_summary is Some(_)).to_string(),
  )
  match observation.observed_summary {
    Some(summary) => {
      lines.push("")
      lines.push(format_device_summary(summary))
    }
    None => ()
  }
  lines.join("\n")
}

///|
pub fn scan_dcp_devices(
  interface_name : StringView,
  timeout_ms? : Int = default_dcp_identify_timeout_ms(),
  xid? : Int = 16909060,
) -> Array[@dcp.DeviceSummary] {
  ignore(
    root_facade_native_handoff_text(
      "scan_dcp_devices",
      "@rawnet.RawSocket::open + @rawnet.local_mac + @rawnet.send/receive",
      [
        "interface=" + interface_name.to_owned(),
        "timeout_ms=" + timeout_ms.to_string(),
        "xid=" + xid.to_string(),
        "result_shape=Array[@dcp.DeviceSummary]",
      ],
    ),
  )
  []
}

///|
pub fn scan_dcp_devices_text(
  interface_name : StringView,
  timeout_ms? : Int = default_dcp_identify_timeout_ms(),
  xid? : Int = 16909060,
) -> String {
  root_facade_native_handoff_text(
    "scan_dcp_devices_text",
    "@rawnet.RawSocket::open + @rawnet.local_mac + @rawnet.send/receive",
    [
      "interface=" + interface_name.to_owned(),
      "timeout_ms=" + timeout_ms.to_string(),
      "xid=" + xid.to_string(),
      "result_shape=String",
    ],
  )
}

///|
fn no_live_observation(
  api_symbol : String,
  legacy_surface : String,
  fields : Array[String],
) -> LiveSetObservation {
  LiveSetObservation::{
    response_text: root_facade_native_handoff_text(
      api_symbol, legacy_surface, fields,
    ),
    observed_set_usage_ms: None,
    observed_summary: None,
  }
}

///|
pub fn live_set_station_name_observation(
  interface_name : StringView,
  destination_mac : StringView,
  station_name : String,
  timeout_ms? : Int = default_dcp_set_get_timeout_ms(),
  observe_window_ms? : Int = 2000,
  xid? : Int = 16909060,
  is_persistent? : Bool = false,
) -> LiveSetObservation {
  no_live_observation(
    "live_set_station_name_observation",
    "@rawnet.RawSocket::open + DCP SetName + DCP Identify observation",
    [
      "interface=" + interface_name.to_owned(),
      "destination_mac=" + destination_mac.to_owned(),
      "station_name=" + station_name,
      "timeout_ms=" + timeout_ms.to_string(),
      "observe_window_ms=" + observe_window_ms.to_string(),
      "xid=" + xid.to_string(),
      "is_persistent=" + is_persistent.to_string(),
    ],
  )
}

///|
pub fn observe_live_set_station_name(
  interface_name : StringView,
  destination_mac : StringView,
  station_name : String,
  timeout_ms? : Int = default_dcp_set_get_timeout_ms(),
  observe_window_ms? : Int = 2000,
  xid? : Int = 16909060,
  is_persistent? : Bool = false,
) -> String {
  format_live_set_observation(
    live_set_station_name_observation(
      interface_name,
      destination_mac,
      station_name,
      timeout_ms~,
      observe_window_ms~,
      xid~,
      is_persistent~,
    ),
  )
}

///|
pub fn live_set_ip_parameters_observation(
  interface_name : StringView,
  destination_mac : StringView,
  address : StringView,
  mask : StringView,
  gateway : StringView,
  timeout_ms? : Int = default_dcp_set_get_timeout_ms(),
  observe_window_ms? : Int = 2000,
  xid? : Int = 16909060,
  is_persistent? : Bool = false,
) -> LiveSetObservation {
  no_live_observation(
    "live_set_ip_parameters_observation",
    "@rawnet.RawSocket::open + DCP SetIP + DCP Identify observation",
    [
      "interface=" + interface_name.to_owned(),
      "destination_mac=" + destination_mac.to_owned(),
      "address=" + address.to_owned(),
      "mask=" + mask.to_owned(),
      "gateway=" + gateway.to_owned(),
      "timeout_ms=" + timeout_ms.to_string(),
      "observe_window_ms=" + observe_window_ms.to_string(),
      "xid=" + xid.to_string(),
      "is_persistent=" + is_persistent.to_string(),
    ],
  )
}

///|
pub fn observe_live_set_ip_parameters(
  interface_name : StringView,
  destination_mac : StringView,
  address : StringView,
  mask : StringView,
  gateway : StringView,
  timeout_ms? : Int = default_dcp_set_get_timeout_ms(),
  observe_window_ms? : Int = 2000,
  xid? : Int = 16909060,
  is_persistent? : Bool = false,
) -> String {
  format_live_set_observation(
    live_set_ip_parameters_observation(
      interface_name,
      destination_mac,
      address,
      mask,
      gateway,
      timeout_ms~,
      observe_window_ms~,
      xid~,
      is_persistent~,
    ),
  )
}

///|
pub fn live_set_station_name(
  interface_name : StringView,
  destination_mac : StringView,
  station_name : String,
  timeout_ms? : Int = default_dcp_set_get_timeout_ms(),
  xid? : Int = 16909060,
  is_persistent? : Bool = false,
) -> String {
  root_facade_native_handoff_text(
    "live_set_station_name",
    "@rawnet.RawSocket::open + DCP SetName",
    [
      "interface=" + interface_name.to_owned(),
      "destination_mac=" + destination_mac.to_owned(),
      "station_name=" + station_name,
      "timeout_ms=" + timeout_ms.to_string(),
      "xid=" + xid.to_string(),
      "is_persistent=" + is_persistent.to_string(),
    ],
  )
}

///|
pub fn live_set_ip_parameters(
  interface_name : StringView,
  destination_mac : StringView,
  address : StringView,
  mask : StringView,
  gateway : StringView,
  timeout_ms? : Int = default_dcp_set_get_timeout_ms(),
  xid? : Int = 16909060,
  is_persistent? : Bool = false,
) -> String {
  root_facade_native_handoff_text(
    "live_set_ip_parameters",
    "@rawnet.RawSocket::open + DCP SetIP",
    [
      "interface=" + interface_name.to_owned(),
      "destination_mac=" + destination_mac.to_owned(),
      "address=" + address.to_owned(),
      "mask=" + mask.to_owned(),
      "gateway=" + gateway.to_owned(),
      "timeout_ms=" + timeout_ms.to_string(),
      "xid=" + xid.to_string(),
      "is_persistent=" + is_persistent.to_string(),
    ],
  )
}

///|
pub fn live_get_dcp_response(
  interface_name : StringView,
  destination_mac : StringView,
  selectors? : StringView = "all",
  timeout_ms? : Int = default_dcp_set_get_timeout_ms(),
  xid? : Int = 16909060,
) -> String {
  root_facade_native_handoff_text(
    "live_get_dcp_response",
    "@rawnet.RawSocket::open + DCP Get",
    [
      "interface=" + interface_name.to_owned(),
      "destination_mac=" + destination_mac.to_owned(),
      "selectors=" + selectors.to_owned(),
      "timeout_ms=" + timeout_ms.to_string(),
      "xid=" + xid.to_string(),
    ],
  )
}