/**********************************************************************
 * Copyright (c) by Heiner Jostkleigrewe
 * This program is free software: you can redistribute it and/or modify it under the terms of the 
 * GNU General Public License as published by the Free Software Foundation, either version 3 of the 
 * License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without 
 *  even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 
 *  the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program.  If not, 
 * see <http://www.gnu.org/licenses/>.
 * 
 * heiner@jverein.de
 * www.jverein.de
 **********************************************************************/
package de.jost_net.JVerein.gui.control;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Date;

import de.jost_net.JVerein.Einstellungen;
import de.jost_net.JVerein.io.Adressbuch.Adressaufbereitung;
import de.jost_net.JVerein.keys.Zahlungsweg;
import de.jost_net.JVerein.rmi.Buchung;
import de.jost_net.JVerein.rmi.Mitglied;
import de.jost_net.JVerein.rmi.Sollbuchung;
import de.willuhn.datasource.GenericIterator;
import de.willuhn.datasource.GenericObject;
import de.willuhn.datasource.GenericObjectNode;
import de.willuhn.datasource.pseudo.PseudoIterator;
import de.willuhn.datasource.rmi.DBIterator;

public class MitgliedskontoNode implements GenericObjectNode
{

  public static final int UNBEKANNT = 0;

  public static final int MITGLIED = 1;

  public static final int SOLL = 2;

  public static final int IST = 3;

  private int type = UNBEKANNT;

  private String id;

  private Mitglied mitglied;

  private String name = null;

  private Date datum = null;

  private String zweck1 = null;

  private String zahlungsweg = null;

  private Double soll = null;

  private Double ist = null;

  private MitgliedskontoNode parent = null;

  private ArrayList<MitgliedskontoNode> children;

  public MitgliedskontoNode(Mitglied m) throws RemoteException
  {
    this(m, null, null);
  }

  public MitgliedskontoNode(Mitglied m, Date von, Date bis)
      throws RemoteException
  {
    type = MITGLIED;
    this.mitglied = m;
    this.zahlungsweg = Zahlungsweg.get(m.getZahlungsweg());
    this.name = Adressaufbereitung.getNameVorname(m);
    this.soll = Double.valueOf(0);
    this.ist = Double.valueOf(0);
    this.children = new ArrayList<>();
    this.id = m.getID();
    DBIterator<Sollbuchung> sollbIt = Einstellungen.getDBService()
        .createList(Sollbuchung.class);
    sollbIt.addFilter(Sollbuchung.MITGLIED + " = ?",
        new Object[] { m.getID() });
    if (von != null)
    {
      sollbIt.addFilter(Sollbuchung.DATUM + " >= ?", von);
    }
    if (bis != null)
    {
      sollbIt.addFilter(Sollbuchung.DATUM + " <= ?", bis);
    }
    sollbIt.setOrder("order by " + Sollbuchung.DATUM + " desc");
    while (sollbIt.hasNext())
    {
      Sollbuchung sollb = (Sollbuchung) sollbIt.next();
      soll += sollb.getBetrag();
      MitgliedskontoNode mkn = new MitgliedskontoNode(this, sollb);
      children.add(mkn);
    }
    for (MitgliedskontoNode node : children)
    {
      for (MitgliedskontoNode nodeist : node.children)
      {
        ist += nodeist.ist;
      }
    }
  }

  public MitgliedskontoNode(MitgliedskontoNode parent, Sollbuchung sollb)
      throws RemoteException
  {
    this.type = SOLL;
    this.parent = parent;
    this.id = sollb.getID();
    this.mitglied = sollb.getMitglied();
    this.zahlungsweg = Zahlungsweg.get(sollb.getZahlungsweg());
    this.datum = sollb.getDatum();
    this.zweck1 = sollb.getZweck1();
    this.soll = sollb.getBetrag();
    this.ist = sollb.getIstSumme();
    if (this.type == SOLL)
    {
      this.children = new ArrayList<>();
      DBIterator<Buchung> it = Einstellungen.getDBService()
          .createList(Buchung.class);
      it.addFilter(Buchung.SOLLBUCHUNG + " = ?",
          new Object[] { sollb.getID() });
      it.setOrder("order by datum desc");
      ist = 0d;
      while (it.hasNext())
      {
        Buchung bist = (Buchung) it.next();
        MitgliedskontoNode mkn = new MitgliedskontoNode(this, sollb, bist);
        ist += bist.getBetrag();
        children.add(mkn);
      }
    }

  }

  public MitgliedskontoNode(MitgliedskontoNode parent, Sollbuchung mk,
      Buchung bist) throws RemoteException
  {
    this.type = IST;
    this.parent = parent;
    this.id = bist.getID();
    this.mitglied = mk.getMitglied();
    this.zahlungsweg = bist.getArt();
    this.datum = bist.getDatum();
    this.zweck1 = bist.getZweck();
    this.ist = bist.getBetrag();
  }

  public int getType()
  {
    return type;
  }

  public Mitglied getMitglied()
  {
    return mitglied;
  }

  @Override
  public String getPrimaryAttribute()
  {
    return null;
  }

  @Override
  public String getID()
  {
    return id;
  }

  @Override
  public String[] getAttributeNames()
  {
    return new String[] { "name", "datum", "zweck1", "zahlungsweg", "soll",
        "ist", "differenz" };
  }

  @Override
  public Object getAttribute(String name)
  {
    if (name.equals("name"))
    {
      return this.name;
    }
    else if (name.equals("datum"))
    {
      return datum;
    }
    else if (name.equals("zweck1"))
    {
      return zweck1;
    }
    else if (name.equals("zahlungsweg"))
    {
      return zahlungsweg;
    }
    else if (name.equals("soll"))
    {
      return soll;
    }
    else if (name.equals("ist"))
    {
      return ist;
    }
    else if (name.equals("differenz"))
    {
      if (ist == null)
      {
        ist = Double.valueOf(0);
      }
      if (type == MITGLIED || type == SOLL)
      {
        double differenz = ist - soll;
        return differenz != 0d ? differenz : null;
      }
      else
      {
        return null;
      }
    }
    return null;
  }

  @Override
  public boolean equals(GenericObject other)
  {
    return false;
  }

  @Override
  public boolean hasChild(GenericObjectNode object)
  {
    return children.size() > 0;
  }

  @Override
  @SuppressWarnings("rawtypes")
  public GenericIterator getPossibleParents()
  {
    return null;
  }

  @Override
  @SuppressWarnings("rawtypes")
  public GenericIterator getPath()
  {
    return null;
  }

  @Override
  public GenericObjectNode getParent()
  {
    return parent;
  }

  @Override
  @SuppressWarnings("rawtypes")
  public GenericIterator getChildren() throws RemoteException
  {
    if (children != null)
    {
      return PseudoIterator
          .fromArray(children.toArray(new GenericObject[children.size()]));
    }
    return null;
  }

  public void remove()
  {
    if (parent != null)
    {
      parent.children.remove(this);
    }
  }

  public Double getSoll()
  {
    return soll;
  }

  public Double getIst()
  {
    return ist;
  }

}
