# Creates JSON output with the following format:
#
# {
#   "lastTimestamp": "20160119171152Z", // most recent modifyTimestamp
#   "project_count": 123,
#   "roster_counts": {
#     "ace": {
#       "members": 20,
#       "owners": 10
#     },
#     "beam": {...}
#     ...
#   },
#   "projects": {
#     "airflow": {
#       "createTimestamp": "20170118154251Z",
#       "modifyTimestamp": "20170118154251Z",
#       "member_count": 123,
#       "owner_count": 123,
#       "members": [
#         "abcd",
#       ],
#       "owners": [
#         "abcd",
#       ],
#        "pmc": true|false, (may be absent)
#        "officer": "abcd", (may be absent)
#        "podling": "current|graduated|retired" (may be absent)
#     },
#     ...
#   },
# }
#

require_relative 'public_json_common'

# Simple class to squash count output
class Counts
  def initialize(hash)
    @hash = hash
  end

  def to_json(*_opts)
    @hash.to_json()
  end
end

# gather project group info
entries = {}

projects = ASF::Project.preload # for performance

if projects.empty?
  Wunderbar.error 'No results retrieved, output not created'
  exit 0
end

# committee status
committees = ASF::Committee.load_committee_info.map {|committee|
  [committee.name.gsub(/[^-\w]/, ''), committee]
}.to_h

# podling status
pods = ASF::Podling.list.map {|podling| [podling.name, podling.status]}.to_h

roster_counts = {}
lastStamp = ''
projects.keys.sort_by(&:name).each do |entry|
  next if entry.name == 'apldap' # infra team would prefer this not be publicized

  m = []
  entry.members.sort_by(&:name).each do |e|
    m << e.name
  end
  o = []
  entry.owners.sort_by(&:name).each do |e|
    o << e.name
  end
  lastStamp = entry.modifyTimestamp if entry.modifyTimestamp > lastStamp
  entries[entry.name] = {
    createTimestamp: entry.createTimestamp,
    modifyTimestamp: entry.modifyTimestamp,
    member_count: m.size,
    owner_count: o.size,
    members: m,
    owners: o
  }
  roster_counts[entry.name] = Counts.new({members: m.size, owners: o.size})
  committee = committees[entry.name]
  if committee
    if committee.pmc?
      entries[entry.name][:pmc] = true
    elsif ASF::Project.find(committee.name).dn
      entries[entry.name][:officer] = committee.chair.id
    end
  end
  pod = pods[entry.name]
  if pod
    entries[entry.name][:podling] = pod
  end
end

info = {
  # Is there a use case for the last createTimestamp ?
  lastTimestamp: lastStamp,
  project_count: entries.size,
  roster_counts: roster_counts,
  projects: entries,
}

public_json_output(info)

if check_now?
  # for validating UIDs
  uids = ASF::Person.list().map(&:id)
  entries.each do |name, entry|
    entry[:members].each do |id|
      Wunderbar.warn "#{name}: unknown member uid '#{id}'" unless uids.include?(id)
    end
    entry[:owners].each do |id|
      Wunderbar.warn "#{name}: unknown owner uid '#{id}'" unless uids.include?(id)
    end
  end
end
