#!/usr/bin/env bash

function group::exists() {
  local name="$1"
  [[ -f "$(ctx::group::path "${name}.group")" ]]
}

function group::require_exists() {
  local name="$1"
  if ! group::exists "$name"; then
    log::error "Group not found: ${name}"
    return 1
  fi
}

function group::path() {
  local name="$1"
  ctx::group::path "${name}.group"
}

function group::peers() {
  local name="$1"
  json::get "$(group::path "$name")" "peers"
}

function group::add_peer() {
  local name="$1" peer="$2"
  json::append "$(group::path "$name")" "peers" "$peer"
}

function group::remove_peer() {
  local name="$1" peer="$2"
  json::remove "$(group::path "$name")" "peers" "$peer"
}

function group::all() {
  local dir
  dir="$(ctx::groups)"
  for f in "${dir}"/*.group; do
    [[ -f "$f" ]] || continue
    basename "$f" .group
  done
}

function group::peer_groups() {
  local peer_name="$1"
  # Returns all groups that contain this peer
  while IFS= read -r group_name; do
    if group::peers "$group_name" | grep -qF "$peer_name"; then
      echo "$group_name"
    fi
  done < <(group::all)
}

function group::remove_peer_from_all() {
  local peer_name="${1:?peer_name required}"
  while IFS= read -r group_name; do
    group::remove_peer "$group_name" "$peer_name"
  done < <(json::peer_groups "$(ctx::groups)" "$peer_name")
}

function group::each_peer() {
  local name="${1:?name required}"
  local callback="${2:?callback required}"
  shift 2
  # $@ = extra args passed to callback

  local peers_list=()
  mapfile -t peers_list < <(group::peers "$name")

  local filtered=()
  for p in "${peers_list[@]:-}"; do
    [[ -n "$p" ]] && filtered+=("$p")
  done

  [[ ${#filtered[@]} -eq 0 ]] && return 0

  for peer_name in "${filtered[@]}"; do
    "$callback" "$peer_name" "$@"
  done
}

function group::_peer_exists_check() {
  local peer_name="${1:-}"
  peers::require_exists "$peer_name" > /dev/null 2>&1
}

function group::has_peer() {
  local group_name="${1:?}" peer_name="${2:?}"
  local group_file
  group_file="$(group::path "$group_name")"
  [[ ! -f "$group_file" ]] && return 1
  local result
  result=$(json::group_has_peer "$group_file" "$peer_name")
  [[ "$result" == "true" ]]
}

