package gov.cms.grouper.snf;

import java.util.function.Function;
import com.mmm.his.cer.foundation.ComponentVersion;
import com.mmm.his.cer.foundation.Processable;
import com.mmm.his.cer.foundation.utility.ComponentClassUtil;
import gov.cms.grouper.snf.lego.SnfComparator;
import gov.cms.grouper.snf.model.SnfComponentAbstract;

public enum SnfComponentVersion implements ComponentVersion {
  r2(100, 104, (dataVersion) -> new gov.cms.grouper.snf.component.r2.SnfComponent(dataVersion)),
  r3(105, 200, (dataVersion) -> new gov.cms.grouper.snf.component.r3.SnfComponent(dataVersion)),;

  private final int from;
  private final int to;
  private final Function<Integer, SnfComponentAbstract> createComponent;



  private SnfComponentVersion(int from, int to,
      Function<Integer, SnfComponentAbstract> createComponent) {
    this.from = from;
    this.to = to;
    this.createComponent = createComponent;
  }


  /**
   * The value used for versioning a Java class path of the {@link Processable} implementation.<br>
   * <br>
   * The return string can be the name of a single package or it can be a partial package path with
   * package names separated by {@link ComponentClassUtil#PACKAGE_SEPARATOR}.<br>
   * <br>
   *
   * @return A valid Java class package name or partial path
   * @see ComponentClassUtil
   */
  @Override
  public String getPackageValue() {
    // TODO Kludge for current package setup, package should be updated to remove component package
    // TODO This will need to change to separate into individual package versions.
    return "component." + name();
  }



  public int getFrom() {
    return from;
  }


  public int getTo() {
    return to;
  }


  public Function<Integer, SnfComponentAbstract> getCreateComponent() {
    return createComponent;
  }


  public static SnfComponentVersion toSnfComponentVersion(int dataVersion) {
    SnfComponentVersion result = null;

    for (SnfComponentVersion rel : SnfComponentVersion.values()) {
      if (SnfComparator.betweenInclusive(rel.from, dataVersion, rel.to)) {
        result = rel;
        break;
      }
    }

    return result;

  }

}
