# $Id: importNOS_JsonReaders.rb 7593 2022-01-05 18:27:39Z flaterco $
# Functions for importNOS.rb:
# JSON file readers

def readTidesJson
  t_array = JSON.parse(File.read("tides.json"))["stations"]
  t = Hash.new
  t_array.each {|s|
    id = s["id"]
    raise "Unhandled: duplicate id in tides.json" if t.include?(id)
    t[id] = s
  }
  t
end

# This isn't the same because the ids aren't unique.  (id + bin)
# Just return the array.
def readCurJson
  # Ignore that line saying "units": "feet"
  JSON.parse(File.read("currents.json"))["stations"]
end

# A particular geogroup appears multiple times in geogroups-tides.json with
# the same geoGroupId but different parents.
# id:  int; name: char; level: int; parents: set of int
Geogroup = Struct.new(:id, :name, :level, :parents)
def readGeogroupsTidesJson
  gt_array = JSON.parse(File.read("geogroups-tides.json"))["geoGroupList"]
  gt = Hash.new
  gt_array.each {|g|
    id = g["geoGroupId"].to_i
    parent = g["parentGeoGroupId"].to_i
    name = g["geoGroupName"]
    level = g["level"].to_i
    if gt.include?(id)
      if gt[id].name != name || gt[id].level != level
	raise "Unhandled: geogroup clash"
      end
      gt[id][:parents].add(parent)
    else
      gt[id] = Geogroup.new(id, name, level, Set.new([parent]))
    end
  }
  gt
end

def readStationsByGroupTidesJson
  sbgt = Hash.new
  Dir.foreach("geogroups") {|groupdir|
    next if groupdir[0] == '.'
    groupjson = File.read("geogroups/#{groupdir}/children.json")
    sbgt_array = JSON.parse(groupjson)["stationList"]
    sbgt_array.each{|sta|
      sid = sta["stationId"]
      # The geogroups themselves are in there with null sids.
      unless sid.nil?
	if sbgt.include?(sid)
	  exist = sbgt[sid]

	  # Special case fixup, 2017; still there, 2021
	  # Station 8730667, Alabama Point, appears in both Florida and Alabama.
	  # 30.2786° N,  87.5550° W
	  # Old name:  Alabama Point, Perdido Pass, Alabama
	  # 1762: Perdido Bay, Gulf Coast-cont., Florida
	  # 1392: Alabama
	  # It is, in fact, just barely in Alabama.  The old name is accurate.
	  if sid == "8730667"
	    sbgt[sid] = sta if sta["parentGeoGroupId"] == "1392"
	    next
	  end

	  # Verify that *only* the level field may disagree in duplicates.
	  sta.each {|k,v|
	    unless k == "level" or exist[k] == v
	      print sid, " ", k, " ", v, " != ", exist[k], "\n"
	      raise "Unhandled: dup conflict in sbgt"
	    end
	  }
	else
	  sbgt[sid] = sta
	end
      end
    }
  }
  sbgt
end

# -tides-
def readStationDatums(sid)
  fname = "tiderefs/" + sid + "/datums.json"
  if File.exist?(fname)
    datums = JSON.parse(File.read(fname))
    raise "Surprise units in datum file" if datums["units"] != "feet"
    datums
  else
    nil
  end
end

# -tides-
def readStationConstants(sid)
  fname = "tiderefs/" + sid + "/harcon.json"
  if File.exist?(fname)
    harcon = JSON.parse(File.read(fname))
    raise "Surprise units in harcon file" if harcon["units"] != "feet"
    harcon["HarmonicConstituents"]   # Array of records
  else
    print "No harmonic constants for requested station ", sid, "\n"
    raise "File not found"
  end
end

# -currents-
# Get harmonic constants and datums for all bins of a current ref station.
# Broken ones like this yield an empty hash:
#   "HarmonicConstituents": [],
# Returns nil if file doesn't exist.
def getCurrentConstForSid(db, aliases, sid)
  fnam = "currefs/#{sid}/harcon.json?units=english"
  if File.exist?(fnam)
    j = JSON.parse(File.read(fnam))["HarmonicConstituents"]
    bins = Hash.new
    j.each {|c|
      bin = c["binNbr"]
      if bins.include?(bin)
	raise "Depth mismatch" if bins[bin][:depth] != c["binDepth"]
	raise "Azimuth mismatch" if bins[bin][:azimuth] != c["azi"]
	raise "Datum mismatch" if bins[bin][:datum] != c["majorMeanSpeed"]
      else
	bins[bin] = {depth: c["binDepth"],
		     azimuth: c["azi"],
		     constants: Hash.new,
                     datum: c["majorMeanSpeed"]}
      end
      constname = c["constituentName"]
      constname = aliases[constname] if aliases.include?(constname)
      bins[bin][:constants][constname] = {amp: c["majorAmplitude"],
	phase: c["majorPhaseGMT"]}
    }
    bins
  else
    nil
  end
end
