package life.catalogue.dao;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import javax.annotation.Nullable;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSession;
import life.catalogue.api.model.*;
import life.catalogue.api.vocab.Datasets;
import life.catalogue.db.mapper.NameMapper;
import life.catalogue.db.mapper.NameUsageMapper;
import org.gbif.nameparser.api.Rank;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MatchingDao {
  private static final Logger LOG = LoggerFactory.getLogger(MatchingDao.class);
  
  private final SqlSession session;
  private final NameUsageMapper uMapper;
  private final NameMapper nMapper;
  
  
  public MatchingDao(SqlSession sqlSession) {
    this.session = sqlSession;
    uMapper = session.getMapper(NameUsageMapper.class);
    nMapper = session.getMapper(NameMapper.class);
  }
  
  public List<? extends NameUsage> matchDataset(SimpleName name, int datasetKey) {
    List<NameUsageBase> matches = new ArrayList<>();
    // https://github.com/Sp2000/colplus-backend/issues/283
    for (NameUsageBase t : uMapper.listByName(datasetKey, name.getName(), name.getRank())) {
      // take authorship, code, status and parent as optional filters, i.e. if null accept any value
      if (StringUtils.trimToNull(name.getAuthorship()) != null && !Objects.equals(name.getAuthorship(), t.getName().authorshipComplete())) {
        continue;
      }
      if (name.getStatus() != null && !Objects.equals(name.getStatus(), t.getStatus())) {
        continue;
      }
      if (name.getCode() != null && !Objects.equals(name.getCode(), t.getName().getCode())) {
        continue;
      }
      matches.add(t);
    }
    if (!matches.isEmpty() && name.getParent() != null) {
      Iterator<NameUsageBase> iter = matches.iterator();
      while(iter.hasNext()) {
        NameUsageBase u = iter.next();
        // https://github.com/Sp2000/colplus-backend/issues/349
        Name parent = nMapper.getByUsage(datasetKey, u.getParentId());
        if (parent == null || !name.getParent().equalsIgnoreCase(parent.getScientificName())) {
          iter.remove();
        }
      }
    }
    return matches;
  }

  public List<Taxon> matchSector(SimpleName name, int sector) {
    return matchSector(name.getName(), name.getAuthorship(), name.getRank(), sector);
  }
  
  public List<Taxon> matchSector(Name name, int sector) {
    return matchSector(name.getScientificName(), name.getAuthorship(), name.getRank(), sector);
  }

  private List<Taxon> matchSector(String name, @Nullable String authorship, @Nullable Rank rank, int sector) {
    List<Taxon> matches = new ArrayList<>();
    for (NameUsage u : uMapper.listByName(Datasets.DRAFT_COL, name, rank)) {
      if (u.isTaxon()) {
        Taxon t = (Taxon) u;
        if (t.getSectorKey() != null && t.getSectorKey().equals(sector)
            && Objects.equals(StringUtils.trimToNull(authorship), StringUtils.trimToNull(u.getName().authorshipComplete()))) {
          matches.add(t);
        }
      }
    }
    return matches;
  }
  
}

@@ -54,35 +54,8 @@
 st;%0A
-import java.util.Iterator;%0A
 impo
@@ -138,98 +138,8 @@
 e;%0A%0A
-import org.apache.commons.lang3.StringUtils;%0Aimport org.apache.ibatis.session.SqlSession;%0A
 impo
@@ -300,24 +300,114 @@
 sageMapper;%0A
+import org.apache.commons.lang3.StringUtils;%0Aimport org.apache.ibatis.session.SqlSession;%0A
 import org.g
@@ -901,32 +901,156 @@
 .class);%0A  %7D%0A  %0A
+  /**%0A   * Strictly matches a simple name to name usages from a given dataset%0A   * @param name%0A   * @param datasetKey%0A   */%0A
   public List%3C? 
@@ -1486,39 +1486,24 @@
 != null && !
-Objects.equals(
 name.getAuth
@@ -1510,18 +1510,34 @@
 orship()
-, 
+.equalsIgnoreCase(
 t.getNam
@@ -1837,290 +1837,346 @@
     
-matches.add(t);%0A    %7D%0A    if (!matches.isEmpty() && name.getParent() != null) %7B%0A      Iterator%3CNameUsageBase%3E iter = matches.iterator();%0A      while(iter.hasNext()) %7B%0A        NameUsageBase u = iter.next();%0A        // https://github.com/Sp2000/colplus-backend/issues/349%0A        Name
+if (name.getParent() != null) %7B%0A        // synonyms already have their parent name. For taxa we need to look that up%0A        // https://github.com/Sp2000/colplus-backend/issues/349%0A        Name parent;%0A        if (t.isSynonym()) %7B%0A          Synonym s = (Synonym) t;%0A          parent = s.getAccepted().getName();%0A        %7D else %7B%0A         
  par
@@ -2212,17 +2212,17 @@
 setKey, 
-u
+t
 .getPare
@@ -2230,16 +2230,26 @@
 tId());%0A
+        %7D%0A
         
@@ -2350,21 +2350,16 @@
     
-iter.remove()
+continue
 ;%0A  
@@ -2366,32 +2366,54 @@
       %7D%0A      %7D%0A
+      matches.add(t);%0A
     %7D%0A    return

Improve parent matching