#!/usr/bin/env ruby

require 'rubygems'
require 'optimist'
#require 'yaml'
#require 'highline'
require 'nokogiri'
require 'fileutils'
require 'htmlentities'

# Initialize our own variables:
mydir=File.expand_path(File.dirname(__FILE__))
testing=""
builddir="build/"
initial_letter=false
new_initial_letter=false
indiv=false


require "#{mydir}/util.rb"

parser = Optimist::Parser.new do
  text "\n\nblah blah blah\n\n---"

  opt :testing, %q{testing mode: will replace all external xrefs in each chapter and turn off the glossary}, :short => 't'
  opt :build_dir, %q{The path of the build dir}, :type => String, :short => 'b'

  stop_on_unknown
end

opts = Optimist::with_standard_exception_handling parser do
  # raise Optimist::HelpNeeded if ARGV.empty? # show help screen
  parser.parse ARGV
end

if opts[:build_dir]
  builddir=opts[:build_dir]
end

# $opts_where=((opts[:where].is_a? String) ? opts[:where].chomp : false)
# $opts_search=((opts[:search].is_a? String) ? opts[:search].chomp : false)

$stderr.puts "Generating glossary entries; this might take a while."

unless opts[:testing]
    $stderr.puts %x{#{mydir}/update_jbovlaste_xml.sh #{builddir}}
    if $?.to_i != 0
      $stderr.puts "jbovlaste file update failed; bailing"
      exit 1
    end
    jbovlaste_tree=Nokogiri::XML(open "#{builddir}/jbovlaste.xml")
end

coder = HTMLEntities.new

md5_1=%x{md5sum "#{builddir}/cll_preglossary.xml"}.chomp.split[0]
md5_2=%x{md5sum "#{builddir}/jbovlaste.xml"}.chomp.split[0]
suffix=''
if opts[:testing]
  suffix='-testing'
end

glossfile="#{builddir}/glossary.xml-#{md5_1}-#{md5_2}#{suffix}"
$stderr.puts "glossfile: #{glossfile}; exists: #{File.exists?(glossfile)} size: #{File.size?(glossfile)}"

if File.exists?(glossfile) and File.size?(glossfile) and File.size?(glossfile) > 100
  $stderr.puts "Glossary file already exists; using."
else
  $stderr.puts "Generating new glossary file."
  File.open(glossfile, 'w') do |gfh|
    tree=Nokogiri::XML(open "#{builddir}/cll_preglossary.xml")
    find_lojban_words( tree ).select { |x| x.attributes['valid'].to_s != 'maybe' }.sort { |a,b| slugify(a.text.to_s).downcase <=> slugify(b.text.to_s).downcase }.map { |x| x.text.to_s.gsub( %r{\.}, '' ) }.uniq.each do |word|
      $stderr.print "#{word} "
      if ! initial_letter
        gfh.puts %q{
<glossary>
<title>Lojban Word Glossary</title>
<para>All definitions in this glossary are brief and unofficial.
Only the published dictionary is a truly official reference for word
definitions.  These definitions are here simply as a quick reference.
</para>

<!-- THIS FILE IS AUTOGENERATED.  DO NOT EDIT OR CHECK IN! -->

        }
      end

      slug=slugify(word)
      #puts "#{word}\t#{slug}"

      new_initial_letter=slug.chars.first.upcase

      if initial_letter != new_initial_letter
        if initial_letter
          gfh.puts "</glossdiv>"
        end
        gfh.puts "<glossdiv><title>#{new_initial_letter}</title>"
        initial_letter=new_initial_letter
      end

      definition=nil
      if opts[:testing]
        definition="placeholder definition"
      else
        definition=jbovlaste_tree.xpath(%Q{//valsi[@word="#{word}"]}).xpath(".//definition").text.strip.gsub(%r{\s+}, ' ')

        # Fix non-xml chars, *before* we add a bunch
        definition = coder.encode(definition, :basic)

        # Turn LaTeX stuff into xml: $1*10^{-2}$]
        definition.gsub!(%r(\$(1\*)?10\^{?([^}$]*)}?\$)){"<dbinlinemath>#{$1}10<superscript>#{$2}</superscript></dbinlinemath>"}

        # Turn LaTeX stuff into xml: $x_{1}= ; then we stop, and repeat
        # this until there's no matches
        olddef=''
        while olddef != definition
          olddef = definition.clone
          definition.gsub!(%r(\$([a-z]+)_{?([0-9]+)}?(=?)), '<dbinlinemath>\1<subscript>\2</subscript></dbinlinemath>\3$')
        end

        # Clean out the remains of the process above
        definition.gsub!(%r{\$\$},'')

        # puts "#{word}, #{definition}"

        if definition =~ %r{\$|\\}
          echo "UNHANDLED LATEX in definiton for $word: $definition"
        end

        if definition =~ %r{^\s*$}
          definition=nil
          $stderr.puts %Q{NO JBOVLASTE DEFINITION FOR "#{word}" FOUND!}
        end
      end

      if definition
        gfh.puts %Q{
<glossentry xml:id="valsi-#{slug}">
<glossterm>#{word}</glossterm>
<glossdef>
  <para>#{definition}</para>
</glossdef>
</glossentry>
        }
      end
    end
    $stderr.puts

    find_lojban_words( tree ).select { |x| x.attributes['valid'].to_s == 'maybe' }.sort { |a,b| slugify(a.text.to_s).downcase <=> slugify(b.text.to_s).downcase }.map { |x| x.text.to_s.gsub( %r{\.}, '' ) }.uniq.each do |word|
      $stderr.puts "valid='maybe' found for word #{word}"
    end

    if initial_letter
      gfh.puts %q{

</glossdiv>
</glossary>

      }
    end
  end
end

puts %x{cat #{glossfile}}
