package ru.micord.ervu.account_applications.component.service;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import model.ComboBoxModel;
import org.springframework.stereotype.Service;
import property.enums.DisplayType;
import property.grid.ColumnSort;
import ru.micord.ervu.account_applications.dao.RecruitmentDao;
import ru.micord.ervu.account_applications.security.context.SecurityContext;
import service.field.ComboBoxServiceImpl;

import ru.cg.webbpm.modules.database.api.bean.TableRow;
import ru.cg.webbpm.modules.database.api.dao.option.LoadOptions;
import ru.cg.webbpm.modules.database.api.dao.option.SortOrder;
import ru.cg.webbpm.modules.database.bean.filter.EntityFilter;
import ru.cg.webbpm.modules.database.bean.filter.FilterOperation;


/**
 * @author Adel Kalimullin
 */
@Service
public class RecruitmentComboBoxService extends ComboBoxServiceImpl {
  private final RecruitmentDao recruitmentDao;
  private final SecurityContext securityContext;
  public RecruitmentComboBoxService(RecruitmentDao recruitmentDao, SecurityContext securityContext) {
    this.recruitmentDao = recruitmentDao;
    this.securityContext = securityContext;
  }


  @Override
  public List<ComboBoxModel> loadData() {
    return load(new LoadOptions());
  }

  @Override
  public List<ComboBoxModel> loadDataWithFilter(Object filterValue) {
    LoadOptions loadOptions = new LoadOptions();
    EntityFilter entityFilter = getFilterColumnEntityFilter(filterValue);
    loadOptions.setEntityFilters(Collections.singletonList(entityFilter));
    return load(loadOptions);
  }

  @Override
  public List<ComboBoxModel> loadDataByParentValueWithFilter(Object parentValue,
      Object filterValue) {
    LoadOptions loadOptions = new LoadOptions();
    List<EntityFilter> entityFilters = new ArrayList<>();
    entityFilters.add(getParentColumnEntityFilter(parentValue));
    if (filterValue != null) {
      entityFilters.add(getFilterColumnEntityFilter(filterValue));
    }
    loadOptions.setEntityFilters(entityFilters);
    return load(loadOptions);
  }

  private EntityFilter getParentColumnEntityFilter(Object parentValue) {
    return parentValue instanceof Collection
           ? new EntityFilter(parentValue, FilterOperation.IN, this.parentControlReference)
           : new EntityFilter(parentValue, FilterOperation.EQUAL, this.parentControlReference);
  }

  private EntityFilter getFilterColumnEntityFilter(Object filterValue) {
    return new EntityFilter(filterValue, FilterOperation.EQUAL_IGNORE_CASE, this.filterColumn);
  }

  private List<ComboBoxModel> load(LoadOptions loadOptions) {
    List<String> recruitmentIds = getRecruitmentIdsForCurrentUser();
    loadOptions.getEntityFilters().add(getEntityFilterForRecruitmentIds(recruitmentIds));
    if (this.columnSorts.length > 0) {
      ColumnSort[] var2 = this.columnSorts;
      int var3 = var2.length;

      for (int var4 = 0; var4 < var3; ++var4) {
        ColumnSort columnSort = var2[var4];
        loadOptions.addSortField(columnSort.field, columnSort.sortOrder);
      }
    }
    else if (this.displayType == DisplayType.MULTI_COLUMN) {
      Arrays.stream(this.displayColumns).forEach((searchDisplayColumn) -> {
        loadOptions.addSortField(searchDisplayColumn.getEntityColumn(), SortOrder.ASC);
      });
    }
    else if (this.displayType == DisplayType.ONE_COLUMN) {
      loadOptions.addSortField(this.displayColumn, SortOrder.ASC);
    }

    Map<String, TableRow> dataMap = this.loadDao.load(this.getColumnsToLoad(), loadOptions)
        .stream()
        .collect(Collectors.toMap(row -> (String)row.get(this.businessIdColumn), row -> row));

    return recruitmentIds.stream()
        .map(dataMap::get)
        .filter(Objects::nonNull)
        .map(this::convertToComboBoxModel)
        .collect(Collectors.toList());
  }

  private List<String> getRecruitmentIdsForCurrentUser() {
    String domainId = securityContext.getDomainId();
    return recruitmentDao.getRecruitmentIdsWithParentByDomainId(domainId);
  }

  private EntityFilter getEntityFilterForRecruitmentIds(List<String> recruitmentIds) {
    return new EntityFilter(recruitmentIds, FilterOperation.IN, this.businessIdColumn);
  }
}