#!/usr/bin/env ruby
#
# written 2007/08/08 and 2007/09/12 by natror
# rewritten for NKJP on 2009/01/14 by natror.

require 'date'
require 'ftools' # for File.copy etc.

require 'jcode' # doesn't redefine String functions but defines its own
$KCODE="u" # or "UTF8" to be verbose

require 'find'

require 'ramkowanie'

  __FILE__ =~ /\/([^\/]+)$/
$myname=$1
$mydirname= File.dirname(__FILE__)

## require "#{mydirname}/script/console"

# bez slasza na końcu nie szło:
## $root_of_all_evil = 
## "wlewka-20100403a/" do 16525
## "wlewka-20100403a/" do 15200 
## "wlewka-20100316/" do 14314
## "wlewka-20100310/" # do 13781
## "wlewka-20100220/" # do 13781
## "wlewka-20100204-infpor/" # do 12711
##  "wlewka-20100122/"
##  "wlewka-20100111/"
## "wlewka-20091210/"
## "wlewka-20091208/"
## "wlewka-20091203/"
## "wlewka-20091130/"
## "wlewka-20091128/"
## "wlewka-20091126/"
## "wlewka-20091123/"
## "wlewka-20091119/"
## "wlewka-20091109-3-małe-wlewki/"
## "wlewka-20091107-sejmIPI/" 
## "wlewka-anotatornia-ochlap-20091106/" 
## "wlewka090910/" 
## "wlewka090909/"
##"produkcja_2009-07-28" 
##"produkcja1" 
##"/tmp/test-plucia" 
##"test3a"

## puts $root_of_all_evil

if $root_of_all_evil[-1] != 47
  $root_of_all_evil +='/'
end


ActiveRecord::Base.connection.execute("pragma synchronous=off;")

$akapit_od = nil
$akapit_do = nil

# bieżący token inicjujemy, tworzymy i zapisujemy 
# być może w różnych podprocedurach, bo musimy zjeść cały
# element <tok>, żeby wiedzieć, czy nie jest to interpunkcja.
$curtoken=nil 


def nowyakapit( morph_xmlid, hasz )
  mocond =  {
    :xmlid => morph_xmlid,
    :path_text => $path}
  mo =  Morph.find( :first, :conditions => mocond )
  mo ||= Morph.create( mocond )
  morphid = mo.id

  aka = Akapit.create(
                    { :morph_id => morphid,
                    :path_id => $pathid }.
                    update( hasz )# xmlid-y
                    )
  $curakapitid = aka.id
  $akapit_od = $curakapitid  unless $akapit_od
  $akapit_do = $curakapitid

  $currtokid = "#{morph_xmlid}.0"
  puts "akapit #{$curakapitid}"
end # of #{nowyakapit}


def tokenbezspacji
  $curtoken.ns_poprzedza = true
end # of #{tokenbezspacji}


nrlextoken=0

def nowytoken( hasz )
  $nrlextoken=0
  $curtoken=Token.create!(
                          { :token_id => $curtokenid, # to ma znaczenie 
                            # przy wczytywaniu interpretacji. 
                            :path_id => $pathid,
                            :czy_interp => false,
                            :akapit_id => $curakapitid }.
                          update( hasz )# tu są oba xmlid-y
                          )
  $curtokenid = $curtoken.id
  $token_od = $curtoken.id  unless defined? $token_od
  $token_do = $curtokenid
end # of #{nowytoken}


def token_orth( orthos )
  $curtoken.orth = orthos # #.nkjp_escape właśnie nie może być eskejpowane, bo już powinno było zostać wyeskejpowane
  # #{.gsub("'", "''")} 2009/03/15 doprowadziło do błędnego wczytania, bo Rails najwyraźniej same podmieniają w~kontaktach z~bazą SQLite3.
end # of #{token_orth}


def token_save
  $curtoken.save!
  $curtoken=nil
end # of #{token_save}


def ustawleksem( lemma, klassag )
  # ustawiamy klasę gram.:
  
  k=KlasaGram.find_by_klasa_gram_ozn( klassag )
  if k
    curkgid=k.klasa_gram_id
  else
    KlasaGram.create( :klasa_gram_ozn => klassag )
    curkgid =  
      KlasaGram.find_by_klasa_gram_ozn( klassag ).klasa_gram_id
  end
  
  leksem_cond = { :path_id =>$pathid, :lemat => lemma, :klasa_gram_id => curkgid }
  l= Leksem.find( :first, :conditions => leksem_cond )
  
  leksem_cond[ :lex_xmlid ] = $currlexhash[ :lex_xmlid ]
  l ||= Leksem.create( leksem_cond )
  ##    puts "leksem |#{lemma}|:|#{klassag}|:|#{curkgid}| created"

  $currlexhash.update( :leksem_id => l.id )
  
end # of #ustawleksem


def set_czy_interp
  if $currctag == "interp"
    $curtoken.czy_interp = true
  else
    $curtoken.czy_interp = false if $curtoken.czy_interp == nil
    # pole czy_interp(unkcja) bieżącego tokenu inicjujemy fałszem tylko gdy
    # nie zostało jeszcze zainicjowane.
  end
end # of #set_czy_interp


def newlexhash( xmlid )
  $nrlextoken+=1
  $currlexhash = {
    :lex_xmlid => xmlid,
    :path_id => $pathid,
    :token_id => $curtokenid, 
    :numer_lex_token => $nrlextoken
  }
end # of #newlexhash


def nowainterpretacja( hasz ) # ten hasz zawiera #{msd_xmlid} oraz #{resztę_tagu}.
  Interpretacja.create(
                       $currlexhash.update( hasz ) # nie ma potrzeby duplikowania #{$currlexhash}\dy  a, bo nowe wartości zastępują stare.
                       )
end # of #{nowainterpretacja}


def relax
end

$we_are_in = []

def badclosure( what_got, what_expected )
  raise "I got </#{what_got}> while expecting </#{what_expected}>!"
end # of #badclosure


def newchoice
  $currchoiceid = SgChoice.create( :akapit_id => $curakapitid_sg ).id
end# of #{newchoice}.

def newvariant
  $currvariantid = SgVariant.create( :sg_choice_id => $currchoiceid ).id
end # of #{newvariant}.

def assign_variant( xpointer, hasz ) # hasz zawiera \sql{segmentation_xmlid} i~\sql{orth} tokenu, który chcemy odnaleźć. 
  tok = Token.find( :first, :conditions => hasz )
  if tok
    tok.xpointer = xpointer
    tok.sg_choice_id = $currchoiceid
    tok.sg_variant_id = $currvariantid
    tok.save
  else raise "token not found: #{hasz.inspect}!"
  end
end# of #{assign_variant}.


def assign_xpointer( xpointer, hasz )
  tok = Token.find( :first, :conditions => hasz )
  if tok
    tok.xpointer = xpointer
    tok.save
  else raise "token not found: #{hasz.inspect}!"
  end
end # of #{assign_xpointer}


def może_nil( text )
  if text.length==0 or text=="NULL" : nil
  else text
  end
end # of #może_nil

def step1( tokxmlid )
  x = $currtokid.split('.')
  x[-1] = x[-1].to_i + 1
  $currtokid = x.join('.')
end # of #step1

with_morphosyntax = true

$paths = []

# Main loop
# Początek głównej zabawy
Find.find( $root_of_all_evil ) { |świzdu|
  ##  puts świzdu
  if świzdu =~ /^(.*)\/ann_pre_morphosyntax\.xml$/ # pliki wejściowe są w~liściach, w~ten sposób upewniamy się więc, że zstąpiliśmy najgłębiej jak można. 
    
    $path = $1
    ##    puts $path
    $paths << $path
  end
}

$paths.sort!

if $paths.size > 0 and  AnoVersion.port == 8003
  `killall anotatornia-keeprunning`
  `./anotatornia-mongrels stop`
  curr_date = `date +%F-%H%M`.chomp
  unless UNatrora.x
    puts "taruję bazę 8003 jako bazy-bk-#{curr_date}.tar.bz2"
    `tar -cjvf bazy-bk-#{curr_date}.tar.bz2 anotatornia_8003.db uzytkownicy_8003.db`
  end
end


## puts $paths.join( "\n" )

## pippi_idx =  $paths.index( "test3a/23.5-Periodyki" )
## if pippi_idx
##  pippi = $paths.delete_at( pippi_idx )
##  $paths = [ pippi ] + $paths
## end

# puts "\n\n" + $paths.join("\n")

$paths.each { |$path|
  
  p =  Path.find_by_path_text( $path )
  if p and with_morphosyntax
    puts "ścieżka #{$path.inspect} już istnieje."
    sleep 0.16666
    ## raise "You're trying import data of the same path #{$path} again!"
  else  
    puts "obrabiam ścieżkę #{$path.inspect}"
    #    sleep 01
    path_path = { :path_text => $path }
    p = ( Path.find( :first, :conditions => path_path ) || 
          Path.create( path_path ) )
    
    $pathid = p.id
    
    if with_morphosyntax
      $currfile = $path + "/ann_pre_morphosyntax.xml"
      File.open( $currfile ) { |f|
        f.each {|line| 
          line.chomp!
          line.strip! if line
          
          case line
            
            ## <p xml:id="morph_8-p" xlink:href="ann_segmentation.xml#segm_8-p">
          when /<p xml:id="morph_(\d+)-p" .*xlink:href="ann_(?:pre_)*segmentation.xml#segm_(\d+)-p">/
              $we_are_in.push( :p )
                    nowyakapit( $1, 
                        {:morphosyntactic_xmlid => $1, 
                          :segmentation_xmlid => $2} 
                        )
            
          when /<seg xml:id="morph_(.*)-seg" xlink:href="ann_(?:pre_)*segmentation.xml#segm_(.*)-seg">/ 
              # wcięcie zwiększone z~powodu krzyżyka w~wyrażeniu regularnym.
              $we_are_in.push( :seg )
            $currtokid = $1
            nowytoken( {:morphosyntactic_xmlid => $1,
                         :segmentation_xmlid => $2 })
            
          when /<seg xml:id="_NOID-ms-seg" xlink:href="ann_(?:pre_)*segmentation.xml#_NOID-sg-seg">/
              $we_are_in.push( :seg )
            nowytoken( {:morphosyntactic_xmlid => ( step1( $currtokid ) ),
                         :segmentation_xmlid => $currtokid })
            
            
          when /<fs type="morph">/
            $we_are_in.push( :fs_morph )
            relax
            
          when /<f name="orth">/        
            $we_are_in.push( :f_orth )
            
          when /<string>(.*)<\/string>/ 
            case  $we_are_in[-1] 
            when :f_base
              $currbase = $1
            when :f_orth
              token_orth( $1 )
            end

          when /<f name="nps"><binary value="true"\/><\/f>/
            tokenbezspacji
            
          when /<f name="interps">/
            $we_are_in.push( :f_interps )
            relax
            
          when /<fs type="lex" xml:id="morph_(.*)-lex">/
            $we_are_in.push( :fs_lex )
            newlexhash( $1 )
            
          when /<fs type="lex" xml:id="_NOID-ms(.*)-lex">/
            $we_are_in.push( :fs_lex )
            newlexhash( $currtokid + $1 )
            
          when /<f name="base">/
            $we_are_in.push( :f_base )
           
          when /<f name="ctag">/
            $we_are_in.push( :f_ctag )

            # warunek  przeniesiony niżej ze względu na kolejność dopasowań

          when /<f name="msd">/
            $we_are_in.push( :f_msd )
            ustawleksem( $currbase, $currctag )

          when /<\/*vAlt>/ # otwarcie ani domknięcie elementu #vAlt nas nie zwilża
            relax
            
          when /<\/f>/
            exp_closure = $we_are_in.pop
            case exp_closure
            when :f_base
              relax
            when :f_ctag
              relax
            when :f_msd
              relax
            when :f_interps
              relax
            when :f_orth
              relax
            else
              badclosure( :f, exp_closure )
            end # of #{case exp_closure}
            
          when /<\/fs>/
            exp_closure = $we_are_in.pop
            case exp_closure
            when :fs_lex
              set_czy_interp
              $currlexhash = nil
            when :fs_morph
              relax
            else
              badclosure( :fs, exp_closure )
            end # of #{case exp_closure}
            
          when /<symbol value="(.*)" xml:id="morph_(.*)-msd"\/>/
            nowainterpretacja( :reszta_tagu => może_nil( $1 ), :msd_xmlid => $2 )
            
          when /<symbol value="(.*)" xml:id="_NOID-ms(.*)-msd"\/>/
            nowainterpretacja( :reszta_tagu => może_nil( $1 ), :msd_xmlid => ( $currtokid + $2 ) )
            
          when /<symbol value="(.*)"\/>/
            $currctag = może_nil( $1)
            
          when /<\/seg>/
            exp_closure = $we_are_in.pop
            if exp_closure == :seg
            else
              badclosure( :seg, exp_closure )
            end
            token_save
            # dopiero tutaj, bo do końca nie wiemy, czy token jest interpuncją,
            # a i~orth dostajemy dopiero wewnątrz elementu <seg>.
            
          when /<\/p>/
            exp_closure = $we_are_in.pop
            if exp_closure == :p
            else
              badclosure( :p, exp_closure )
            end
            
          when /<!--(.*)-->/
            if $we_are_in[-1] ==  :fs_morph
              $curtoken.fs_morph_comment = $1.strip
            end 
            puts line
            
          else
            puts line
          end
        } # of each line of the file,
      } # Ruby closes the file.
      
    end # of #{ if with_morphosyntax}
    
    $currfile = $path + "/ann_pre_segmentation.xml"
    File.open( $currfile ) {|f| 
      f.each {|line| 
        line.chomp!
        
        line_OK=true
        
        case line
          ## <p xml:id="segm_1-p" xlink:href="text.xml#txt_1.1-ab">
        when /<p xml:id="segm_(\d+)-p".*xlink:href="(.*)">/
          $we_are_in.push( :p )
          aka = Akapit.find( :first, :conditions =>
                             { :segmentation_xmlid => $1,
                               :path_id => $pathid }
                             )
          if aka : $curakapitid_sg = aka.id
            aka.segmentation_xlink_href = $2
            aka.save!
            puts "dodałam xlink_href w akapicie #{$1}"
          else raise "Akapit not found! Sought segmentation_xmlid: #{$1} and path_id: #{$pathid}."
          end
          
        when /<choice>/
          $we_are_in.push( :choice )
          newchoice
          
        when /<nkjp:paren>/
          $we_are_in.push( :nkjp_paren )
          newvariant
           
          ## <seg xml:id="segm_8.1-seg"><xi:include href="text.xml" xpointer="string-range(txt_8.1-ab,0,1)"/></seg>   <!-- - -->
        when /<seg xml:id="segm_([^"]*)-seg".*xpointer="(.*)".*<\/seg>.*<!-- (.+) -->/
          ##/<seg xml:id="segm_1.2727-seg" nkjp:nps="true">em<\/seg>/
          # Nie sprawdzamy, czy wartość #nps w~pliku \file{sg} jest taka sama, jak w~pliku \file{ms}. 
          hasz = { :akapit_id => $curakapitid_sg, 
            :segmentation_xmlid => $1, 
            :orth => $3.nkjp_escape }
          if $we_are_in.include?( :choice )
            if $we_are_in[-1] == :choice
              newvariant
            end
            assign_variant( 
                           $2, # xpointer
                                             hasz )
          else 
            assign_xpointer( $2, hasz )
          end
        
        when /<\/nkjp:paren>/
          exp_closure = $we_are_in.pop
          unless exp_closure == :nkjp_paren
            badclosure( :nkjp_paren, exp_closure )
          end

        when /<\/choice>/
          exp_closure = $we_are_in.pop
          unless exp_closure == :choice
            badclosure( :choice, exp_closure )
          end
          
        when /<\/p>/
          exp_closure = $we_are_in.pop
      unless exp_closure == :p
        badclosure( :p, exp_closure )
      end
          
        else puts line
          
        end  #of #{case line} 
      }# of each line of \file{sg.xml}
    }# closing file.
      
      
    end # of main if
  
} # of each path.

## Statusy.find( :first ) # żeby zainicjować resztę tabel


puts Time.now
puts "inicjuję Transzę, AkapitTranszy i Statusy (m.in. od #{$akapit_od} do #{$akapit_do})"
Transza.zrob_transze( :pełne )
Statusy.uzupełnij_tabelę ## ( $akapit_od, $akapit_do )
# to nie ma argumentów, bo tabelę trzeba uzupełnić tak, by dane były spójne.

## puts Time.now
## puts "dopuszczam posegmentowane od #{$akapit_od} do #{$akapit_do}"
## Akapit.dopuść_posegmentowane( $akapit_od, $akapit_do )
# powyższe wykonuje się już w~poprzedniej zwrotce.

puts Time.now
puts "zaznaczam końce ostatnich zdań  (m.in. od #{$akapit_od} do #{$akapit_do})"
Akapit.zaznacz_końce_ostatnich_zdań ##( $akapit_od, $akapit_do )

puts Time.now
puts "dezambiguuję interpunkcje (m.in. od #{$akapit_od} do #{$akapit_do})"
Akapit.zdezambiguuj_interpunkcje ##( $akapit_od, $akapit_do )

puts Time.now
puts "ustawiam ns_nastepuje  (m.in. od #{$akapit_od} do #{$akapit_do})"
Token.update_ns_nastepuje ## ( $akapit_od, $akapit_do )

puts Time.now
puts "inicjuję PoziomyAnotacji"
PoziomyAnotacji.nadąż_za_użytkownikiem

puts Time.now
puts "dodaję  »kolejnosc« w tabeli token"
Token.update_kolejnosc

puts Time.now
puts "dodaję  »kolejnosc« w tabeli token"
CzMLeksem.przypisz_leksemom_i_interpretacjom # to przypisze też cz.m. leksemom, jeśli nie była.
Akapit.autozatwierdź_word_senses # to w szczególności dopuści word_senses gdzie należy.

puts Time.now
puts "wpisuję incipity akapitów"
Akapit.update_treści_null

puts "poprawiam SHY"
Token.gsub_SHY

## puts "usuwam puste"
## Akapit.usuń_puste
# w razie odkomentowania tego do czasu obsługi płatnej doliczyć 15 min.

puts " # do #{Akapit.maximum( :akapit_id )}"

true



exit # żeby odblokować bazę.

# about ranges: file:///usr/share/doc/rubybook/html/tut_stdtypes.html

# very instructive: /usr/lib/ruby/1.8/jcode.rb

### Local Variables:
### coding: utf-8
### mode: ruby
### End:
