
package de.ivu.elect.business.protokollierung.boundary;

import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;

import de.ivu.elect.business.protokollierung.entity.EntityTechnicalNamePkNode;
import de.ivu.elect.business.protokollierung.entity.ProtokollEintrag;
import de.ivu.elect.business.protokollierung.entity.ProtokollEintragDefaultComparator;
import de.ivu.elect.business.protokollierung.entity.QProtokollEintrag;
import de.ivu.elect.jee.entity.EntityTechnicalNamePk;
import de.ivu.elect.jee.entity.QueryDsl;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.jee.protokollierung.ProtokollEintragArt;

public class ProtokollEintragSearch extends AbstractProtokollEintragSearch {

  @Inject
  private transient Messages messages;

  public ProtokollEintragSearch() {
    super();
  }

  @Override
  protected List<ProtokollEintrag> querySearchResult(ProtokollEintragSearchParameters searchParameters) {
    List<ProtokollEintrag> result = new ArrayList<>();

    String entityLokalisiert = messages.getMessageForMessageKey(searchParameters.getEntityTechnicalNamePk().getTechnicalName());

    result.addAll(lokalisiereNameDerEntitaet(getProtokollEintraegeFuerEntityTechnicalNamePk(searchParameters.getEntityTechnicalNamePk()), entityLokalisiert));

    for (EntityTechnicalNamePkNode entityTechnicalNamePkNode : searchParameters.getChildren()) {
      addResultForNode(result, entityTechnicalNamePkNode, entityLokalisiert);
    }

    result.sort(new ProtokollEintragDefaultComparator(messages));

    return result;
  }

  private void addResultForNode(List<ProtokollEintrag> result, EntityTechnicalNamePkNode entityTechnicalNamePkNode, String parentLabel) {
    String entityLokalisiert = parentLabel + "-" + messages.getMessageForMessageKey(entityTechnicalNamePkNode.getEntityTechnicalNamePk().getTechnicalName());

    // Für abhängige Entitäten die "Anlegen"-Einträge filtern, da diese dem Eintrag der fachlichen Entität entsprechen
    result.addAll(
        filterTyp(lokalisiereNameDerEntitaet(getProtokollEintraegeFuerEntityTechnicalNamePk(entityTechnicalNamePkNode.getEntityTechnicalNamePk()), entityLokalisiert), ProtokollEintragArt.ANLEGEN));

    for (EntityTechnicalNamePkNode technicalNamePkNode : entityTechnicalNamePkNode.getChildren()) {
      addResultForNode(result, technicalNamePkNode, entityLokalisiert);
    }
  }

  private List<ProtokollEintrag> filterTyp(List<ProtokollEintrag> eintraege, ProtokollEintragArt art) {
    List<ProtokollEintrag> result = new ArrayList<>(eintraege.size());

    for (ProtokollEintrag protokollEintrag : eintraege) {
      if (!art.equals(protokollEintrag.getProtokollEintragArt())) {
        result.add(protokollEintrag);
      }
    }

    return result;
  }

  public List<ProtokollEintrag> lokalisiereNameDerEntitaet(List<ProtokollEintrag> eintraege, String entityLokalisiert) {
    for (ProtokollEintrag protokollEintrag : eintraege) {
      protokollEintrag.setEntityLabel(entityLokalisiert);
    }

    return eintraege;
  }

  public List<ProtokollEintrag> getProtokollEintraegeFuerEntityTechnicalNamePk(EntityTechnicalNamePk entityTechnicalNamePk) {
    QueryDsl query = dao.getQueryDsl();
    query.getQuery().from(QProtokollEintrag.protokollEintrag);

    addSearchParameters(query, entityTechnicalNamePk);

    return query.getQuery().fetch();
  }

  protected void addSearchParameters(QueryDsl query, EntityTechnicalNamePk entityTechnicalNamePk) {
    QProtokollEintrag protokollEintragTable = QProtokollEintrag.protokollEintrag;
    query.eq(protokollEintragTable.entitaet, entityTechnicalNamePk.getTechnicalName());
    query.eq(protokollEintragTable.primaerschluessel, entityTechnicalNamePk.getId());
  }
}
