/**
   * @see de.willuhn.jameica.hbci.io.Exporter#doExport(java.lang.Object[],
   *     de.willuhn.jameica.hbci.io.IOFormat, java.io.OutputStream, de.willuhn.util.ProgressMonitor)
   */
  public void doExport(Object[] objects, IOFormat format, OutputStream os, ProgressMonitor monitor)
      throws RemoteException, ApplicationException {
    if (objects == null || !(objects instanceof UmsatzTree[]))
      throw new ApplicationException(i18n.tr("Bitte wählen Sie die zu exportierenden Umsätze aus"));

    UmsatzTree[] t = (UmsatzTree[]) objects;
    if (t.length == 0)
      throw new ApplicationException(i18n.tr("Bitte wählen Sie die zu exportierenden Umsätze aus"));

    UmsatzTree tree = t[0];
    List list = tree.getUmsatzTree();
    Konto k = tree.getKonto();

    String subTitle =
        i18n.tr(
            "Zeitraum {0} - {1}, {2}",
            HBCI.DATEFORMAT.format(tree.getStart()),
            HBCI.DATEFORMAT.format(tree.getEnd()),
            k == null ? i18n.tr("alle Konten") : k.getBezeichnung());

    Reporter reporter = null;
    try {
      reporter = new Reporter(os, monitor, i18n.tr("Umsatzkategorien"), subTitle, list.size());

      reporter.addHeaderColumn(i18n.tr("Kategorie"), Element.ALIGN_CENTER, 130, Color.LIGHT_GRAY);
      reporter.addHeaderColumn(i18n.tr("Einnahmen"), Element.ALIGN_CENTER, 30, Color.LIGHT_GRAY);
      reporter.addHeaderColumn(i18n.tr("Ausgaben"), Element.ALIGN_CENTER, 30, Color.LIGHT_GRAY);
      reporter.addHeaderColumn(i18n.tr("Betrag"), Element.ALIGN_CENTER, 30, Color.LIGHT_GRAY);
      reporter.createHeader();

      // Iteration ueber die Kategorien
      for (int i = 0; i < list.size(); ++i) {
        renderNode(reporter, (UmsatzTreeNode) list.get(i), 0);
        reporter.setNextRecord();
      }
      if (monitor != null) monitor.setStatus(ProgressMonitor.STATUS_DONE);
    } catch (Exception e) {
      if (monitor != null) monitor.setStatus(ProgressMonitor.STATUS_ERROR);
      Logger.error("error while creating report", e);
      throw new ApplicationException(
          i18n.tr("Fehler beim Erzeugen der Auswertung: {0}", e.getMessage()), e);
    } finally {
      if (reporter != null) {
        try {
          reporter.close();
        } catch (Exception e) {
          Logger.error("unable to close report", e);
        }
      }
    }
  }
  /**
   * @see de.willuhn.jameica.hbci.io.Exporter#doExport(java.lang.Object[],
   *     de.willuhn.jameica.hbci.io.IOFormat, java.io.OutputStream, de.willuhn.util.ProgressMonitor)
   */
  public void doExport(Object[] objects, IOFormat format, OutputStream os, ProgressMonitor monitor)
      throws RemoteException, ApplicationException {
    if (os == null)
      throw new ApplicationException(i18n.tr("Kein Ausgabe-Ziel für die Datei angegeben"));

    if (format == null) throw new ApplicationException(i18n.tr("Kein Ausgabe-Format angegeben"));

    if (objects == null || objects.length == 0)
      throw new ApplicationException(i18n.tr("Keine zu exportierenden Daten angegeben"));

    if (!(objects instanceof SammelTransfer[]))
      throw new ApplicationException(
          i18n.tr("Die zu exportierenden Daten enthalten keine Sammel-Aufträge"));

    DtausDateiWriter writer = null;

    try {
      writer = new DtausDateiWriter(os);
      for (int i = 0; i < objects.length; ++i) {
        SammelTransfer transfer = (SammelTransfer) objects[i];
        Konto konto = transfer.getKonto();
        GenericIterator buchungen = transfer.getBuchungen();

        monitor.setPercentComplete(0);
        monitor.setStatusText(i18n.tr("Exportiere logische Datei Nr. {0}", "" + (i + 1)));

        double factor = 100d / buchungen.size();
        int count = 0;
        int success = 0;

        long kundenNummer = 0;
        String s = konto.getKundennummer();
        try {
          kundenNummer = Long.parseLong(s);
        } catch (Exception e) {
          monitor.log(i18n.tr("Ignoriere Kundennummer {0}: ungültig", s));
        }

        long blz = 0;
        s = konto.getBLZ();
        try {
          blz = Long.parseLong(s);
        } catch (Exception e) {
          monitor.log(i18n.tr("Ignoriere BLZ {0}: ungültig", s));
        }

        writer.open();
        writer.setAAusfuehrungsdatum(transfer.getTermin());
        writer.setABLZBank(blz);

        String type = (transfer instanceof SammelUeberweisung) ? "GK" : "LK";
        writer.setAGutschriftLastschrift(type);

        writer.setAKonto(Long.parseLong(konto.getKontonummer()));
        writer.setAKundenname(konto.getName());
        writer.writeASatz();

        while (buchungen.hasNext()) {
          // Mit diesem Factor sollte sich der Fortschrittsbalken
          // bis zum Ende der DTAUS-Datei genau auf 100% bewegen
          monitor.setPercentComplete((int) ((++count) * factor));

          SammelTransferBuchung buchung = (SammelTransferBuchung) buchungen.next();

          monitor.log(i18n.tr("Exportiere Datensatz {0}", buchung.getGegenkontoName()));

          writer.setCBetragInEuro(buchung.getBetrag());
          writer.setCBLZEndbeguenstigt(Long.parseLong(buchung.getGegenkontoBLZ()));
          writer.setCBLZErstbeteiligtesInstitut(blz);
          writer.setCKonto(Long.parseLong(buchung.getGegenkontoNummer()));
          writer.setCName(buchung.getGegenkontoName());
          writer.setCInterneKundennummer(kundenNummer);
          writer.setCTextschluessel(mapTextschluesselToDtaus(buchung));

          String[] lines = VerwendungszweckUtil.toArray(buchung);
          for (String line : lines) writer.addCVerwendungszweck(line);

          writer.writeCSatz();
          success++;
        }
        monitor.setStatusText(i18n.tr("{0} Aufträge erfolgreich exportiert", "" + success));
      }
      writer.writeESatz();
    } catch (OperationCanceledException oce) {
      Logger.info("operation cancelled");
      monitor.setStatusText(i18n.tr("Export abgebrochen"));
      monitor.setStatus(ProgressMonitor.STATUS_CANCEL);
    } catch (ApplicationException ae) {
      throw ae;
    } catch (DtausException dta) {
      Logger.error(dta.getMessage(), dta);
      throw new ApplicationException(i18n.tr(dta.getLocalizedMessage()));
    } catch (Exception e) {
      throw new RemoteException(i18n.tr("Fehler beim Export der Daten"), e);
    } finally {
      if (writer != null) {
        try {
          writer.close();
          os = null;
        } catch (Exception e) {
          Logger.error("error while closing dtaus writer", e);
        }
      }
      // Outputstream schliessen, falls das noch nicht geschehen ist
      if (os != null) {
        try {
          os.close();
        } catch (Throwable t) {
          Logger.error("unable to close file", t);
        }
      }
    }
  }