ruleset edu.byu.enMotion.building.grouper {
  meta {
    use module edu.byu.enMotion.building alias building
    shares __testing, by_prefix
  }
  global {
    __testing = { "queries": [ { "name": "__testing" },
                               { "name": "by_prefix", "args": [ "name_prefix" ] } ],
                  "events": [ {"domain":"grouper","type":"creation","attrs":["name_prefix"]}] }
    //-----------------------------------
    //compute array of dispenser picos whose names have a given prefix
    //
    by_prefix = function(name_prefix) {
      prefix_re = ("^"+name_prefix).as("RegExp");
      building:dispenser_rooms().filter(function(v){v like prefix_re})
    }
    //-----------------------------------
    //obtain subscription request ECI for a dispenser pico, or null
    //
    get_wellKnown_eci = function(eci) {
      url = meta:host+"/sky/cloud/"+eci+"/io.picolabs.subscription/wellKnown_Rx";
      http:get(url.klog("url")){"content"}.decode(){"id"}
    }
  }
  //-----------------------------------
  //start process to create a group-of-dispensers pico
  //asking for a new child pico
  //
  rule collection_needed {
    select when grouper creation
    pre {
      name_prefix = event:attr("name_prefix");
      group_name = name_prefix + " Rooms";
      rids = "io.picolabs.collection;io.picolabs.subscription";
      child_specs = { "name": group_name, "name_prefix": name_prefix,
        "rids": rids, "color": "#002e5d" };
    }
    fired {
      raise wrangler event "new_child_request" attributes child_specs;
    }
  }
  //-----------------------------------
  //start process to create a group-of-dispensers pico
  //verify that all dispenser picos can do subscriptions
  //
  rule collection_creation {
    select when grouper creation
    fired {
      raise grouper event "need_subscribability" attributes event:attrs;
    }
  }
  //-----------------------------------
  //verify that all dispenser picos can do subscriptions
  //for any that don't, install the io.picolabs.subscription ruleset
  //
  rule collection_subscription_check {
    select when grouper need_subscribability
    foreach by_prefix(event:attr("name_prefix")) setting(v,k)
    pre {
      tag_id = k.klog("tag_id");
      room_name = v.klog("room_name");
      eci = building:eci(tag_id);
      wellKnown_Tx = get_wellKnown_eci(eci).klog("wellKnown_Tx");
    }
    if wellKnown_Tx.isnull() then every {
      send_directive(tag_id,{"eci":eci,"room_name":room_name});
      event:send({"eci":eci,"domain":"wrangler","type":"install_rulesets_requested",
        "attrs": { "rid": "io.picolabs.subscription" }
      })
    }
  }
  //-----------------------------------
  //when the new group-of-dispensers pico is ready for use
  //obtain its subscription request ECI
  //
  rule collection_subscriptions {
    select when wrangler child_initialized
    pre {
      eci = event:attr("eci").klog("child_eci");
      collection_eci = get_wellKnown_eci(eci).klog("collection_eci")
    }
    if collection_eci then noop();
    fired {
      raise grouper event "need_subscriptions"
        attributes event:attr("rs_attrs").put("collection_eci",collection_eci)
    }
  }
  //-----------------------------------
  //have each dispenser pico propose a subscription to the collection pico
  //
  rule collection_subscription_requests {
    select when grouper need_subscriptions
    foreach by_prefix(event:attr("name_prefix")) setting(v,k)
    pre {
      tag_id = k.klog("tag_id");
      room_name = v.klog("room_name");
      eci = building:eci(tag_id);
      wellKnown_Tx = get_wellKnown_eci(eci).klog("wellKnown_Tx");
    }
    if wellKnown_Tx then every {
      event:send({"eci":eci,"domain":"wrangler","type":"subscription",
        "attrs": { "wellKnown_Tx": event:attr("collection_eci"),
          "Rx_role": "member", "Tx_role": "collection",
          "name": tag_id, "channel_type": "subscription" }
      })
    }
  }
}