
package de.ivu.elect.presentation.gebietsbaum.tree;

import java.io.Serializable;
import java.util.function.Function;

import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.GebietPK;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.presentation.gebietsbaum.GebietNummerFormatter;

public class GebietsbaumTreeNodeData implements Serializable {

  private static final long serialVersionUID = 1L;

  private final String name;

  private final GebietPK pk;

  private final String nummer;

  private final String icon;

  private final String title;

  private final boolean isDynamicIcon;

  private final GebietsbaumTreeNodeIconResolver gebietsbaumTreeNodeIconResolver;

  private final Function<GebietPK, Gebiet> gebietLoader;

  private final String nameNummerFormatiert;

  private final boolean isSelectable;
  private final boolean isEditable;

  public GebietsbaumTreeNodeData(Gebiet gebiet, GebietsbaumTreeNodeIconResolver gebietsbaumTreeNodeIconResolver, Messages messages, Function<GebietPK, Gebiet> gebietLoader,
      GebietNummerFormatter gebietNummerFormatter, boolean isSelectable, boolean isEditable) {
    super();

    this.isSelectable = isSelectable;
    this.isEditable = isEditable;

    this.pk = gebiet.getPk();

    this.name = gebiet.getName();
    this.nummer = gebietNummerFormatter.getNummer(gebiet);
    this.nameNummerFormatiert = getNameNummerFormatiert(gebiet,  gebietNummerFormatter); // ELECTMUC-2305
    this.title = bestimmeTitle(gebiet, gebietsbaumTreeNodeIconResolver, messages);

    this.icon = bestimmeIcon(gebiet, gebietsbaumTreeNodeIconResolver);
    this.isDynamicIcon = bestimmeIsDynamicIcon(gebiet, gebietsbaumTreeNodeIconResolver);

    if (this.isDynamicIcon) {
      this.gebietsbaumTreeNodeIconResolver = gebietsbaumTreeNodeIconResolver;
      this.gebietLoader = gebietLoader;
    } else {
      this.gebietsbaumTreeNodeIconResolver = null;
      this.gebietLoader = null;
    }
  }

  private static String getNameNummerFormatiert(Gebiet gebiet, GebietNummerFormatter gebietNummerFormatter) {
    return gebietNummerFormatter.getDetailMitMarkierungenIcons(gebiet, gebietNummerFormatter::getDarstellung);
  }

  private String bestimmeTitle(Gebiet gebiet, GebietsbaumTreeNodeIconResolver gebietsbaumTreeNodeIconResolver, Messages messages) {
    return gebietsbaumTreeNodeIconResolver.getTitle(gebiet, messages);
  }

  private String bestimmeIcon(Gebiet gebiet, GebietsbaumTreeNodeIconResolver gebietsbaumTreeNodeIconResolver) {
    return gebietsbaumTreeNodeIconResolver.getIcon(gebiet);
  }

  private boolean bestimmeIsDynamicIcon(Gebiet gebiet, GebietsbaumTreeNodeIconResolver gebietsbaumTreeNodeIconResolver) {
    return gebietsbaumTreeNodeIconResolver.isDynamicIcon(gebiet);
  }

  public String getIcon() {
    if (isDynamicIcon) {
      return gebietsbaumTreeNodeIconResolver.getDynamischesIcon(icon, ()->gebietLoader.apply(pk));
    }
    return icon;
  }

  public String getTitle() {
    if (isDynamicIcon) {
      return gebietsbaumTreeNodeIconResolver.getDynamischenTitle(title, ()->gebietLoader.apply(pk));
    }
    return title;
  }

  public String getName() {
    return name;
  }

  public String getNummer() {
    return nummer;
  }

  public String getNameNummerFormatiert() {
    if (isDynamicIcon) {
      return gebietsbaumTreeNodeIconResolver.getDynamischenNameNummerFormatiert(nameNummerFormatiert, ()->gebietLoader.apply(pk));
    }
    return nameNummerFormatiert;
  }

  public String getStyleClass() {
    if (!isSelectable()) {
      return "noSelectableTreeNode";
    }

    if (!isEditable()) {
      return "noEditableTreeNode";
    }
    return "";
  }

  public boolean isEditable() {
    return isEditable;
  }

  @Override
  public String toString() {
    return getName();
  }

  public GebietPK getPk() {
    return pk;
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + (pk == null ? 0 : pk.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    GebietsbaumTreeNodeData other = (GebietsbaumTreeNodeData) obj;
    if (pk == null) {
      if (other.pk != null) {
        return false;
      }
    } else if (!pk.equals(other.pk)) {
      return false;
    }
    return true;
  }

  public boolean isSelectable() {
    return isSelectable;
  }
}
