# $Id: importNOS_TideSubs.rb 6953 2018-12-24 21:51:23Z flaterco $
# Functions for importNOS.rb:
# Tidal subordinate station import

# Messiness happens because every field wants to be fixed up using some other
# field that is also unreliable or incomplete.  Something has to go first.

def importTideSubs(db)
  if File.exist?("renamings-tidesubs.sql")
    puts "Don't want to overwrite renamings-tidesubs.sql; do something with it"
    exit
  end
  gt = readGeogroupsTidesJson()
  sbgt = readStationsByGroupTidesJson()
  stateMap = getOldStateMap(db)
  wAleutSids = getWesternAleutians(db)
  tides = readTidesJson()
  File.open("renamings-tidesubs.sql","w") {|renamings|
    tides.each_value {|tsta|

      # "type" is R = reference, S = subordinate, X = undocumented

      raise "Notices are not null anymore" unless tsta["notices"].nil?
      raise "Disclaimers are not null anymore" unless tsta["disclaimers"].nil?

      tname = tsta["name"]
      sid = tsta["id"]
      if isMaybeNotFreeData(gt, sbgt, tsta)
	# stationLongGeogroupName is less informative about why things are
	# dropped because some levels get suppressed.
	print "Skipped ", sid, " ", tname, " (blacklisted)\n"
	next
      end

      refid = tsta["reference_id"]
      offsets = tsta["tidepredoffsets"]
      raise "Mismatched ref IDs" if offsets["refStationId"] != refid

      type = tsta["type"]
      raise "Mismatched types" if offsets["type"] != type

      lat = tsta["lat"]
      lng = tsta["lng"]
      if lng < 0 && westernAleutian?(gt, sbgt, wAleutSids, tname, sid)
	print "Fixing longitude of ", sid, " ", tname, "\n"
	lng = -lng
      end
      maxl = offsets["heightOffsetHighTide"]  # multiply OR add
      minl = offsets["heightOffsetLowTide"]   # multiply OR add
      maxt = offsets["timeOffsetHighTide"]    # minutes
      mint = offsets["timeOffsetLowTide"]     # minutes
      adjtyp = offsets["heightAdjustedType"]  # R (mult) or F (add)

      # 2017: there are 125 records in tides.json where the refids are
      # missing or self-referential yet there are offsets.  For those
      # checked, tidesandcurrents.noaa.gov only brings up the reference
      # station.  If we have constants for it then treat those offsets as
      # spurious.
      if refid.empty? or sid == refid
	unless (maxl.nil? or maxl == 0) and (minl.nil? or minl == 0) and
	    (maxt.nil? or maxt == 0) and (mint.nil? or mint == 0)
	  unless type == "R" and refStationExists(db, sid)
	    print "CHECK: ", sid, " ", tname, "\n"
	    raise "Station check"
	  end
	end
	next
      end

      unless refStationExists(db, refid)
	print "Skipped ", sid, " ", tname, " (missing ref ", refid, ")\n"
	next
      end

      raise "Nil offsets" if maxl.nil? or minl.nil? or maxt.nil? or mint.nil?
      raise "Zero multiplier" if adjtyp == "R" and (maxl.zero? or minl.zero?)

      case adjtyp
      when "R"
	minla, minlm, maxla, maxlm = [nil, minl, nil, maxl]
      when "F"
	minla, minlm, maxla, maxlm = [minl, nil, maxl, nil]
      else
	raise "Unknown heightAdjustedType"
      end

      # For name/state/timezone, we have three options.
      # 1 - harmonize with existing reference station
      # 2 - keep from data_sets_old
      # 3 - guess
      oldtuple = getRefNameStateTz(db, sid)
      oldtuple = getOldNameStateTz(db, sid) if oldtuple.nil?
      if oldtuple.nil?
	state = guessState(gt, sbgt, stateMap, tsta, lat, lng)
	name = guessLongStationName("", tname, state,
				    stationLongGeogroupName(gt, sbgt, sid))
	tz = guessTimezone(state, name, lat, lng)
      else
	name, state, tz = oldtuple
      end
      raise "State might be nil but should not be empty" if !state.nil? and state.empty?
      name = name.gsub("D.C.","DC").gsub("F.S.M.","FSM")
      name = name.chomp(" (2)").chomp(" (sub)")

      country = guessCountry(state, name)
      if type == "X"
	notes = "Station type is undocumented type X; maybe a deleted record; use with caution."
      else
	notes = nil
      end

      # Time warps and other meridian problems
      submerid = TZmerids[tz]
      if submerid.nil?
	print "Missing from TZmerids: ", tz, "\n"
	raise "Missing tz"
      end
      # tsta["timemeridian"] is garbage.
      reftz = getRefTimezone(db, refid)
      if reftz != tz
	refmerid = TZmerids[reftz]
	if refmerid.nil?
	  print "Missing from TZmerids: ", reftz, "\n"
	  raise "Missing tz"
	end
	if refmerid != submerid
	  print "Time warp at ", sid, " ", name, "\n"
	  print "  Ref ", refid, " is ", reftz, " (merid ", refmerid, ")\n"
	  print "  Sub is ", tz, " (merid ", submerid, ")\n"
	  adjustMin = (refmerid - submerid) * 60
	  mint += adjustMin
	  maxt += adjustMin
	  notes = append(notes, "Reference is in time zone " + reftz +
			 "; adjusted offsets " + (refmerid-submerid).to_s +
			 " hr\nto undo LST compensation.\n")
	end
      end

      # Resolve name clashes
      if refStationNamed(db, name)
	name += " (sub)"
	if nameInUse(db, name)
	  raise "Adding sub wasn't enough"
	end
      elsif nameInUse(db, name)
	stupidSuffixNumber = 1
	begin
	  stupidSuffixNumber += 1
	  tryname = name + " (" + stupidSuffixNumber.to_s + ")"
	end while nameInUse(db, tryname)
	name = tryname
      end

      xfields = "Credit:NOAA data processed by David Flater for XTide\n https://flaterco.com/xtide/"

      if oldtuple.nil?
	mname = mangle(name)
	renamings.print "-- #{sid}\n-- #{tname}\n-- lat #{lat} lon #{lng}\nupdate data_sets\n  set name = '#{mname}'\n  where name = '#{mname}';\n"
      end

      mint = mint.to_s + " minutes"
      maxt = maxt.to_s + " minutes"
      comments = nil                 # Saved for future use
      res = db.exec("insert into data_sets (name, original_name, station_id_context, station_id, lat, lng, timezone, state, country, units, source, notes, comments, restriction, xfields, ref_index, min_time_add, min_level_add, min_level_multiply, max_time_add, max_level_add, max_level_multiply) values ($1, $2, 'NOS', $3, $4, $5, $6, $7, $8, 'feet', 'CO-OPS Metadata API', $9, $10, 'Public domain', $11, $12, $13, $14, $15, $16, $17, $18)", [name, tname, sid, lat, lng, tz, state, country, notes, comments, xfields, getRefIndex(db,refid), mint, minla, minlm, maxt, maxla, maxlm])
    }
  }
end
