
package de.ivu.elect.business.search.control;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.Nullable;
import javax.inject.Inject;

import de.ivu.elect.business.system.control.CustomContextParameter;
import de.ivu.elect.jee.entity.QueryDsl;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.jee.presentation.dynamicform.LambdaLongProperty;
import de.ivu.elect.jee.presentation.dynamicform.Property;
import de.ivu.elect.jee.presentation.search.AbstractSearchParameters;
import de.ivu.elect.presentation.search.SuchparameterSpeicherbar;


import static java.util.Objects.nonNull;

/**
 * ELECT-4018 - Suchparameter speichern
 */
public class AbstractElectSearchParameters extends AbstractSearchParameters implements SuchparameterSpeicherbar, CustomContextParameter {

  private static final long serialVersionUID = 1L;

  public static final Long NO_LIMIT = null;

  public static final Long GLOBAL_MASSENDATEN_DEFAULT_LIMIT = 1000L;

  public static final Long GLOBAL_MAX_LIMIT = 50000L;

  public static final AbstractElectSearchParameters EMPTY = new AbstractElectSearchParameters();

  @Inject
  protected transient SearchParameterStateExtractor searchParameterStateExtractor;

  @Inject
  protected transient Messages messages;

  private Long limit = getDefaultLimit();

  private transient Property limitProperty;

  private Map<String, Object> contextParameters;

  public AbstractElectSearchParameters() {
    super();
  }

  @Override
  public String getSearchParameterState() {
    return searchParameterStateExtractor.getSearchParameterState(this);
  }

  @Override
  public void setSearchParameterState(String stateAsString) {
    searchParameterStateExtractor.setSearchParameterState(this, stateAsString);
  }

  @Nullable
  protected Long getDefaultLimit() {
    return NO_LIMIT;
  }

  public Long getLimit() {
    return limit;
  }

  public void setLimit(Long limit) {
    this.limit = limit;
  }

  public Property getLimitPropertyNoLimit() {
    return getLimitProperty(NO_LIMIT);
  }

  public Property getLimitProperty(Long maxLimit) {
    if (limitProperty == null) {
      limitProperty = new LambdaLongProperty(getMessage("search.filter.max.anzahl.treffer.label"), maxLimit != null, this::setLimit, this::getLimit, 1L, maxLimit, null);
    }

    return limitProperty;
  }

  public QueryDsl applyLimit(QueryDsl queryDsl) {
    if (nonNull(getLimit()) && getLimit() > 0L) {
      queryDsl.limit(getLimit().intValue());
    }

    return queryDsl;
  }

  protected String getMessage(String msgKey, Object... params) {
    return getMessages().getMessageForMessageKey(msgKey, params);
  }

  protected String getMessage(Enum< ? > enumValue) {
    return getMessages().lokalisiere(enumValue);
  }

  protected Messages getMessages() {
    return messages;
  }

  @Override
  public void reset() {
    super.reset();

    limit = getDefaultLimit();
  }

  @Override
  public Map<String, Object> getContextParameters() {
    if (contextParameters == null) {
      contextParameters = new ConcurrentHashMap<>();
    }
    return contextParameters;
  }
}
