require 'spongiae/unit'

require 'nokogiri'
require 'zip'

module Spongiae
   module Formats
       
       class OpenDocCallbacks < Nokogiri::XML::SAX::Document
           
           def initialize(sub)
               @sub = sub; @id = 0; @text = ''
           end
           
           def start_element(name, attrs = []) start_element_namespace(name,attrs) end
               
           def start_element_namespace(name, attrs = [], prefix = nil, uri = nil, ns = [])
               @id = @id + 1 if name =~ /^(p|h)$/ and prefix == 'text'
           end
           
           def end_element_namespace(name, prefix = nil, uri = nil)
               if name =~ /^(p|h)$/ and prefix == 'text' then 
                   @sub.call Spongiae::Unit::Unilingual.new(@file, @id.to_s, nil, @text)
                   @text = ''
               end
           end
           
           def characters(text) 
               if @id != nil then @text = @text + text end
           end
       end
       
       class OpenDocCallbacksOutput <  OpenDocCallbacks
           def initialize(dest,sub)
               super(sub); @dest = dest
           end
           
           def start_element_namespace(name, attrs = [], prefix = nil, uri = nil, ns = [])
               super(name, attrs, prefix, uri, ns)
               if prefix == nil then @dest.print "<#{name}" else @dest.print "<#{prefix}:#{name}" end
               ns.each { |item| @dest.print " xmlns:#{item[0]} = \"#{item[1]}\"" } if name =~ /document-content/
               attrs.each { |item| @dest.print " #{item[0]} = \"#{item[1]}\"" }
               @dest.print ">"               
           end
           
           def end_element_namespace(name, prefix = nil, uri = nil)
               super(name, prefix, uri)
               if prefix == nil then @dest.print "</#{name}>" else @dest.print "</#{prefix}:#{name}>" end
           end
           
           def characters(text) 
               if @id != nil then 
                   @text = @text + text 
               else
                   @dest.print text
               end
           end
       end
       
       
       class OpenDocFile
           
           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)
               Zip::File.foreach(@file) do |entry|
                    if entry.name =~ /content\.xml/ then                       
                        callback = OpenDocCallbacks.new(sub)
                        parser = Nokogiri::XML::SAX::Parser.new(callback)
                        parser.parse(entry.get_input_stream)
                    end
               end
           end
           
           def translate(dest_file_name,translations_map,props={})
               Zip::OutputStream.open(dest_file_name) do |outs|
                   Zip::File.foreach(@file) do |entry|
                        outs.put_next_entry entry.name
                        if entry.name =~ /content\.xml/ then                       
                           callback = OpenDocCallbacksOutput.new(outs, Proc.new { |unit|
                                tra = unit.text
                                tra = translations_map[unit.id] if translations_map[unit.id] != nil
                                outs.puts tra
                            })
                           parser = Nokogiri::XML::SAX::Parser.new(callback)
                           parser.parse(entry.get_input_stream)
                        else
                            outs.copy_raw_entry entry                            
                        end
                   end
               end                   
           end
           
       end
       
   end
end
