# -*- coding: utf-8 -*-
#
# xml_art17_exporter.rb
# (c) ENDA, 2016
#
#     Bitte für jede Berichtsperiode die Exportkonstanten (@data[]) neu eintragen
#     und die alten Konstanten NICHT ENTFERNEN, sondern @PERIOD neu einstellen!
# 
# by mlt
#
# Rel-1-3-1
# 2016-06-16, mlt: Fertig entwickelt

class Art17_XML_Exporter
  attr :glade
  attr :dbh

  def initialize(glade)
    @glade = glade
    @file_num_lines = 0
    @bar = @glade['progressbar1']
    self.pulse
    @odoc = nil
    @oroot = nil
    @data = Hash.new

    @PERIOD = 'DE2014'
    @data[['DE2014', 'flarepCode']] = 'DE_UWWT_2014_1'
    @data[['DE2014', 'soecCode']] = 'DEUWWINV2013'
    @data[['DE2014', 'soecStartYear']] = '2013-01-01'
    @data[['DE2014', 'soecEndYear']] = '2013-12-31'
    @data[['DE2014', 'soecPeriod']] = 'CU'                # CU - current, EXP - expected, P - past
    @data[['DE2014', 'soecCapacity']] = 151831032
    @data[['DE2014', 'soecInvCol']] = 2090
    @data[['DE2014', 'soecInvTp']] = 788
    @data[['DE2014', 'soecInvComments']] = 'Daten für den Bezugszeitraum 2014 liegen derzeit noch nicht vor.; soecCapacity: Betrifft derzeitige Ausbaugröße (Bemessungskapazität gemäß Genehmigungsbescheid) bezogen auf öffentliche Abwasserbehandlungsanlagen ab mindestens 50 EW (p.e.) Ausbaugröße; Datenquelle: Statistisches Bundesamt (Fachserie 19 Reihe 2.2.2) 2013; Erhebung alle 3 Jahre; soecInVCol und soecTp: wirtschaftliche Kennzahlen, darunter auch Investitionszahlen für den Bereich Abwasserentsorgung werden separat im Rahmen der Statistik des produzierenden Gewerbes (Fachserie 4 Reihe 6.1) jährlich seit 2008 vom Statistischen Bundesamt erhoben und publiziert (https://www.destatis.de/GPStatistik/receive/DESerie_serie_00000070) . Die Berichte erscheinen frühestens 18 Monate nach Ablauf des Berichtzeitraumes. Vorher waren die Informationen unter "Energie- und Wasserversorgung" subsumiert und daher nicht separat ausweisbar. Die Erhebungspflicht besteht für Unternehmen der Abwasserentsorgung, die eine jährliche Schmutzwassermenge von 200.000 m³ und mehr behandeln. Dies deckt sich in etwa mit dem Geltungsbereich der Kommunalabwasserrichtlinie. Ein wichtiges Ergebnis dieser Erhebung sind die getätigten Investitionen. Den größten Anteil bei den Investitionen haben die Investitionen in technische Anlagen und Maschinen. Diese werden in der Statistik separat ausgewiesen. Davon werden u.a. Investitionen in Leitungs- und Rohrnetz separat ausgewiesen und hier als Investitionen in Kanalnetz angenommen. Die Angaben zu Investitionen in Anlagen ergeben sich aus der Differenz der Investitionen in technische Anlagen und Maschinen und in Kanalnetz. Zahlen zu geplanten Investitionen werden nicht erhoben und liegen daher nicht vor.'
    @data[['DE2014', 'flaconReportedPeriod']] = 2013
    @data[['DE2014', 'flaconVersion']] = '2016-06-16'
    @data[['DE2014', 'flaconSituationAt']] = '2013-12-31'
    @data[['DE2014', 'flaconName']] = 'Dr. Joachim Heidemeier'
    @data[['DE2014', 'flaconInstitution']] = 'Umweltbundesamt'


    # Einziger Method-Call von außen: export, s.u.
  end

  def pulse
    @bar.pulse
    Gtk.main_iteration
  end

  def export
    @bar.pulse_step = 0.07
    @bar.fraction = 0.0
    @bar.text="exporting"
    pulse
    puts "Die zu exportierende XML Datei wird hier hin geschrieben: #{MY_CONSTANT_ART17_XML_PATH}"
    puts "Start am/um #{Stnd.now}"
    anydoc = self.open_document
    self.create_document
    self.write_document

    @bar.text="done"
    @bar.fraction = 1.0
    puts "Ende am/um #{Stnd.now}"
  end

  def open_document
    pulse
    @odoc = XML::Document.new()
    @odoc.encoding = XML::Encoding::UTF_8
    @odoc.root = XML::Node.new('UWWTD_Data')
    pulse
    XML::Namespace.new(@odoc.root, 'xs', 'http://www.w3.org/2001/XMLSchema')
    XML::Namespace.new(@odoc.root, 'dd1', 'http://dd.eionet.europa.eu/namespace.jsp?ns_id=1')
    XML::Namespace.new(@odoc.root, 'dd3', 'http://dd.eionet.europa.eu/namespace.jsp?ns_id=3')
    XML::Namespace.new(@odoc.root, 'dd2', 'http://dd.eionet.europa.eu/namespace.jsp?ns_id=2')
    XML::Namespace.new(@odoc.root, 'dd850', 'http://dd.eionet.europa.eu/namespace.jsp?ns_id=850')
    XML::Namespace.new(@odoc.root, 'dd851', 'http://dd.eionet.europa.eu/namespace.jsp?ns_id=851')
    XML::Namespace.new(@odoc.root, 'dd853', 'http://dd.eionet.europa.eu/namespace.jsp?ns_id=853')
    XML::Namespace.new(@odoc.root, 'dd866', 'http://dd.eionet.europa.eu/namespace.jsp?ns_id=866')
    pulse
    return @odoc
  end

  def create_document
    @odoc.root << report = XML::Node.new('UWWTD_Report')
    xml_date = Time.now.strftime("%Y-%m-%dT%H:%M:%S.000+01:00")
    report['rptDateexported'] = xml_date
    pulse
    report << investments = create_investments
    report << contacts = create_contact

    puts "\nDocument created"

  end

  def create_investments
    investments = XML::Node.new('FLAInvestments')
    investments << investment = XML::Node.new('FLAInvestment')
    # setting an attribute example: investment['status'] = 'medium-rare'
    puts "Period ist #{@PERIOD}"
    puts "@data ist: #{@data}"
    poke(investment, @data[[@PERIOD, 'flarepCode']], 'dd853:flarepCode')
    poke(investment, @data[[@PERIOD, 'soecCode']], 'dd853:soecCode')
    poke(investment, @data[[@PERIOD, 'soecStartYear']], 'dd853:soecStartYear')
    poke(investment, @data[[@PERIOD, 'soecEndYear']], 'dd853:soecEndYear')
    poke(investment, @data[[@PERIOD, 'soecPeriod']], 'dd853:soecPeriod')
    poke(investment, @data[[@PERIOD, 'soecCapacity']], 'dd853:soecCapacity')
    poke(investment, @data[[@PERIOD, 'soecInvCol']], 'dd853:soecInvCol')
    poke(investment, @data[[@PERIOD, 'soecInvTp']], 'dd853:soecInvTp')
    poke(investment, @data[['DE2014', 'soecInvComments']], 'dd853:soecInvComments')
    pulse
    return investments
  end

  def create_contact
    contact = XML::Node.new('FLAContact')
    poke(contact, 'DE', 'dd866:flaconMemberState')
    poke(contact, @data[[@PERIOD, 'flarepCode']], 'dd866:flarepCode')
    poke(contact, @data[[@PERIOD, 'flaconReportedPeriod']], 'dd866:flaconReportedPeriod')
    poke(contact, @data[[@PERIOD, 'flaconVersion']], 'dd866:flaconVersion')
    poke(contact, @data[[@PERIOD, 'flaconSituationAt']], 'dd866:flaconSituationAt')
    poke(contact, @data[[@PERIOD, 'flaconName']], 'dd866:flaconName')
    poke(contact, @data[[@PERIOD, 'flaconInstitution']], 'dd866:flaconInstitution')
    pulse
    return contact
  end

  def inspect_doc
    @odoc.root.namespaces.each{ |namespace|
      puts "Namespace #{namespace.prefix} : #{namespace.node_type} : #{namespace.to_s}"
    }
  end

  def write_document
    @odoc.save(MY_CONSTANT_ART17_XML_PATH, :indent => true, :encoding => XML::Encoding::UTF_8)

    @bar.text="validating..."
    # inspect_doc

    puts "#{MY_CONSTANT_ART17_XML_PATH} gespeichert."

    # valdoc = @odoc
    valdoc = XML::Document.file(MY_CONSTANT_ART17_XML_PATH)

    schema_document = XML::Document.file('../schemata/UWWTD_Art17.xsd')
    schema = XML::Schema.document(schema_document)
    pulse
    STDOUT.flush
    STDERR.flush
    begin
      result = valdoc.validate_schema(schema) do |message, is_error|
        # Das kann man sich getrost in die Haare reiben, denn validate_schema schmeißt eine Exception...
        if is_error
          puts "ERROR!"
        else
          puts "WARNING!"
        end
        puts "Anfang der Meldung:"
        puts message
        puts "Ende der Meldung."
      end
    rescue Exception => wumm
      pulse
      puts "Exception <#{wumm}>."
      # print wumm.backtrace.join("\n")
      puts
    end
    if result
      puts "Das Dokument ist bzgl. des Schemas perfekt"
    else
      puts "Das Dokument kann noch besser werden"
    end
  end


  # fill_node looks whether the column of row has a content
  # if so, it creates an element inside node and fills it with the content
  def fill_node (node, row, column_name, element_name)
    if row[column_name]
      node << var = XML::Node.new(element_name)
      var << row[column_name]
    end
  end

  # fill_node_bool does it like fill_node and converts numeric boolean
  # values 0/1 to false/true to fulfill COM XML Schema requirements
  def fill_node_bool(node, row, column_name, element_name)
    if row[column_name]
      node << var = XML::Node.new(element_name)
      var << (row[column_name] == 1 ? 'true' : 'false')
    end
  end


  def fill_node_yesno(node, row, column_name, element_name)
    if row[column_name]
      node << var = XML::Node.new(element_name)
      var << (row[column_name] == 1 ? 'Y' : 'N')
    end
  end


  def fill_node_10(node, row, column_name, element_name)
    if row[column_name]
      node << var = XML::Node.new(element_name)
      var << (row[column_name] == 1 ? '1' : '0')
    end
  end


  def fill_node_compliance(node, row, column_name, element_name)
    if row[column_name] && row[column_name] != 3
      value = case row[column_name]
                when 1, 4 then 'P'
                when 2 then 'F'
              # when 4 then 'NR'
                else raise Exception.new, "ERROR: xml_art15_exporter.rb, fill_node_compliance, case: else reached"
              end
      node << var = XML::Node.new(element_name)
      var << value
    end
  end

  # poke takes a content and looks if it is not nil
  # if not nil, it creates an element inside node and fills it with the content
  def poke (node, content, element_name)
    if content
      node << var = XML::Node.new(element_name)
      var << content
    end
  end

  def testexport
    puts "Die zu exportierende XML Datei wird hier hin geschrieben: #{MY_CONSTANT_ART17_XML_PATH}"
    puts "Start am/um #{Stnd.now}"

    # mydoc = XML::Document.file('../daten/e_kommu_art17.xml')
    mydoc = XML::Document.file('../daten/e_kommu_art17_oxygen.xml')
    schema_document = XML::Document.file('../schemata/UWWTD_Art17.xsd')
    schema = XML::Schema.document(schema_document)
    pulse
    STDOUT.flush
    STDERR.flush
    begin
      result = mydoc.validate_schema(schema) do |message, is_error|
        if is_error
          puts "ERROR!"
        else
          puts "WARNING!"
        end
        puts "Anfang der Meldung:"
        puts message
        puts "Ende der Meldung."
      end
    rescue Exception => wumm
      pulse
      puts "Exception <#{wumm}>."
      # print wumm.backtrace.join("\n")
      puts
    end
    if result
      puts "Das Dokument ist bzgl. des Schemas perfekt"
    else
      puts "Das Dokument kann noch besser werden"
    end

    puts "Ende am/um #{Stnd.now}"
  end

end
