require 'gdbm'

class String
  def htquote
    gsub(/[&'"<>]/) {|c|
      case c
      when '&' then '&amp;'
      when '"' then '&quot;'
      when "'" then '&apos;'
      when '<' then '&lt;'
      when '>' then '&gt;'
      else c
      end
    }.gsub(
    /(2[0-9]{3}-[01][0-9]-[0-3][0-9])T([012][0-9]:[0-5][0-9]:[0-6][0-9])Z?/
    ) {
      "#$1 #$2"
    }.gsub(/P0Y0M0DT(\d+)H0M0S/) {
      "Every #$1 hours"
    }
  end
end

STDD = "background-color: #CCF; text-decoration: line-through double"
STDM = "background-color: #CCF; text-decoration: line-through double"
STAA = "background-color: #FFC; text-decoration: underline dotted"
STAM = "background-color: #FFC; text-decoration: underline dotted"

$prev = (ENV['PREVDATE'] || 'unknown')
$now = (ENV['NOWDATE'] || Time.now.utc.strftime('%Y-%m-%dT%HZ'))
$dbfnam = (ENV['CATDB'] || 'z.database')
$n = 0
inkey = {}

$hdr = %w( id heading OAI-date status dateStamp bounds policy format kw.temporal
  kw.place title poc gisc )

def dspk key, skipwis = false
  kq = key.htquote
  h = []
  h.push "<p>Links: "
  unless skipwis
    h.push "<a href='http://www.wis-jma.go.jp/meta/search.jsp?text=#{key.gsub(/\W/, '_')}'>WIS Metadata</a> "
  end
  h.push "<a href='http://toyoda-eizi.net/wmo9/volc1/ahl/#{key}'>VolC1</a></p>\n"
  h.join
end

def dspw term
  case term
  when /\A\d{5}\z/
    "<a href='http://toyoda-eizi.net/wmo9/vola/idxnum/#{term}'>#{term}</a>"
  when /\A(\d{5}) [A-Z][-\w ]+\z/
    "<a href='http://toyoda-eizi.net/wmo9/vola/idxnum/#{$1}'>#{term}</a>"
  when /\A\[(-90\.?0*:90\.?0* -180\.?0*:180\.?0*)\]\z/
    "#{term} <i>(whole globe)</i>"
  when /\A\[([-+.: 0-9]+)\]\z/
    "<a href='http://toyoda-eizi.net/wmo9/bbox/#{$1.gsub(/[ :]/, ',')}'>#{term}</a>"
  when /\A(WMOEssential|WMOAdditional|WMOOther|NoLimitation)\z/
    "<a href='http://redmine.toyoda-eizi.net/projects/wcmp/wiki/WMO_DataLicenseCode##{$1}'>#{term}</a>"
  when /\A(ICAO )?(AMDAR|BUFR|CLIMAT|CREX|IAC|METAR|PILOT|SAREP|SATOB|SHIP|SIGMET|SPECI|SYNOP|TAF|TEMP)([- ][ A-Zxt.]*)?(\(FM ?\d+\))?\z/
    "<a href='http://redmine.toyoda-eizi.net/projects/wcmp/wiki/Common_Data_Formats##{$2}'>#{term}</a>"
  when /\A(FM ?\d\d)([-A-Za-z0-9. ]*)\z/
    "<a href='http://redmine.toyoda-eizi.net/projects/wcmp/wiki/Common_Data_Formats##{$1.sub(/ /, '')}'>#{term}</a>"
  else
    term.htquote
  end
end

def dspc s, dif = {}
  case s
  when /\A\|.*\|\z/
    s.split(/\|/).map{|t|
      next if t.empty?
      if dif[t] then "<b>#{dspw(t)}</b>"
      else dspw(t)
      end
    }.join(" ")
  when '|' then '&nbsp;'
  else
    dspw(s)
  end
end

def dsp1 key, val, flg
  col = if flg == 'INS' then STAA else STDD end
  a = val.split(/,/, 11)
  return if a[1] == 'deleted'
  $n = $n.succ
  #flg,#oaiId,#oaiDate,#oaiStatus,#recordDate,#bbox,#dataPolicy,#fmt,#hours,#places,#title
  h = []
  a.size.times {|i|
    s = a[i]
    k = $hdr[i + 2]
    h.push "<p><em>#{k}:</em> <span id='d#{$n}.#{k.downcase}' style='#{col}'>#{dspc(s)}</span></p>\n"
  }
  h.unshift "<hr /><div id='ahl.#{key}'><h2 id='d#{$n}' style='#{col}'>#{$n} #{flg} #{key.htquote}</h2>\n"
  h.push dspk(key, flg == 'INS')
  h.push "</div>"
  puts h.join
end

def dsp2 key, oval, val
  a = oval.split(/,/, 11)
  b = val.split(/,/, 11)
  return if a[1] == 'deleted' and b[1] == 'deleted'
  return dsp1(key, oval, 'DEL') if b[1] == 'deleted'
  return dsp1(key, val, 'INS') if a[1] == 'deleted'
  return if a[1,10] == b[1,10]
  $n = $n.succ
  h = []
  h.push "<hr /><div id='ahl.#{key}'>"
  h.push "<h2 id='d#{$n}'>#{$n} MODIFY #{key.htquote}</h2>\n"
  a.size.times {|i|
    ai, bi = a[i], b[i]
    k = $hdr[i + 2]
    kd = k.downcase
    aa = ai.split(/\|/)
    ba = bi.split(/\|/)
    dif = {}
    (aa - ba).each{|t| dif[t] = true}
    (ba - aa).each{|t| dif[t] = true}
    if ai == bi then
      h.push "<p><em>#{k}:</em> <span id='d#{$n}.#{kd}'>#{dspc(ai, dif)}</span></p>\n"
    else
      h.push "<p><em>#{k}:</em><blockquote id='d#{$n}.#{kd}'>"
      h.push "<p>DEL: <span style='#{STDM}' id='d#{$n}.#{kd}.dm'>#{dspc(ai, dif)}</span>"
      h.push "<p>INS: <span style='#{STAM}' id='d#{$n}.#{kd}.am'>#{dspc(bi, dif)}</span></blockquote></p>\n"
    end
    dif = nil

  }
  h.push dspk(key)
  h.push "</div>"
  puts h.join
end

GDBM.open($dbfnam, 0666) {|hdb|
  puts <<HTML
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8861-1" />
<title>WIS MD Changes #{$prev.htquote}/#{$now.htquote}</title>
<style type="text/css">
p { margin: 1px; }
</style>
</head>
<body>
<div id="page">
<h1>WIS Metadata Changes for GTS Bulletins</h1>
<p>Since: <b style="#{STDD}" id="since">#{$prev.htquote}</b></p>
<p>Until: <b style="#{STAA}" id="until">#{$now.htquote}</b></p>
<p>This is an unofficial summary made by TOYODA Eizi,
compiled from WIS Discovery Metadata collected at GISC Tokyo.
This is not an official notification from WMO nor JMA.</p>
<!--more-->
HTML
  for line in ARGF
    next if /^#/ === line
    key, val = line.chomp.split(/,/, 2)
    inkey[key] = true
    oval = hdb.fetch(key, nil)
    if oval then
      unless oval == val
	dsp2(key, oval, val)
      end
    else
      dsp1(key, val, 'INS')
    end
    oval = val = nil
  end
  hdb.each {|key, oval|
    next if inkey[key]
    dsp1(key, val, 'DEL')
  }
  puts <<HTML
<hr />
<p>Number of changes: <b id="nchanges">#{$n}</b></p>
</div>
</body></html>
HTML
}