require 'spongiae/unit'

require 'anguilla'
require 'set'

module Spongiae
   module Formats
       
       class DocbookCallbacks
           include REXML::StreamListener
           
           def initialize(sub)
               @sub = sub
               @path = ''; @text = ''
               @keys = Set.new
           end
           
           def tag_start(element, attributes)
               @path = @path + "/#{element}"
               if attributes['id'] != nil and attributes['id'].length > 0 then
                   @path = @path + "[id=#{attributes['id']}]"
               else
                   i = 0; i = i + 1 while @keys.include? "#{@path}[#{i}]"
                   @keys.add "#{@path}[#{i}]"
                   @path = "#{@path}[#{i}]"
               end
           end
           
           def tag_end(element)
               if element =~ /^para|title$/ then 
                   @text.strip!
                   @text.gsub! /\n/, ' '
                   @text.gsub! /\s+/, ' '
                   @sub.call Spongiae::Unit::Unilingual.new(@file, @path, nil, @text)
                   @text = ''
               end
               @path = @path[0, @path.rindex('/')] if @path.rindex('/') != nil
           end
           
           def text(text) 
               if @path != nil and @path.rindex('indexterm') == nil then @text = @text + text end
           end
       end
       
       class DocbookCallbacksOutput <  DocbookCallbacks
           def initialize(dest,sub)
               super(sub); @dest = dest
           end
           
           def tag_start(element, attributes)
               super(element, attributes)
               @dest.print "<#{element}"
               attributes.each_pair { |k,v| @dest.print " #{k} = \"#{v}\"" }
               @dest.print ">"               
           end
           
           def tag_end(element)
               super(element)
               @dest.print "</#{element}>"
           end
           
           def text(text) 
               if @path != nil and @path.rindex('indexterm') == nil then 
                   @text = @text + text 
               else
                   @dest.print text
               end
           end
       end
       
       class Docbook
           
           def initialize(file, props = {})
               @file = file
           end
           
           # read_strings : build unit for each string
           # For Plain Text, this is one string per line.
           def read_unit(&sub)
               callback = DocbookCallbacks.new(sub)
               Anguilla::parse(@file,callback)
           end
           
           def translate(dest_file_name,translations_map,props={})
               File.open(dest_file_name, 'w:UTF-8') do |dest|
                  dest.puts <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "../../../docbook-xml-4.5/docbookx.dtd">
EOF
                  callback = DocbookCallbacksOutput.new(dest, Proc.new { |unit|
                      tra = unit.text
                      tra = translations_map[unit.id] if translations_map[unit.id] != nil
                      dest.puts tra
                    })
                  Anguilla::parse(@file,callback)
              end
           end
           
       end
       
   end
end
