package gov.cms.grouper.snf.model.reader;

import static gov.cms.grouper.snf.model.AssessmentType.ARD;
import static gov.cms.grouper.snf.model.AssessmentType.CALCULATED_HIPPS;
import static gov.cms.grouper.snf.model.AssessmentType.CALCULATED_VERSION;
import static gov.cms.grouper.snf.model.AssessmentType.COGNITIVE;
import static gov.cms.grouper.snf.model.AssessmentType.DIET_MECHANICAL;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_BED_MOBILITY_TO_LYING;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_BED_MOBILITY_TO_LYING_IPA;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_BED_MOBILITY_TO_SITTING;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_BED_MOBILITY_TO_SITTING_IPA;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_EATING;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_EATING_IPA;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_HYGIENE_ORAL;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_HYGIENE_ORAL_IPA;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_HYGIENE_TOILET;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_HYGIENE_TOILET_IPA;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_TRANSFER_CHAIR;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_TRANSFER_CHAIR_IPA;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_TRANSFER_TOILET;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_TRANSFER_TOILET_IPA;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_TRANSFER_TO_STANDING;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_TRANSFER_TO_STANDING_IPA;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_WALKING_150_FEET;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_WALKING_150_FEET_IPA;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_WALKING_50_FEET;
import static gov.cms.grouper.snf.model.AssessmentType.FUNCTIONAL_WALKING_50_FEET_IPA;
import static gov.cms.grouper.snf.model.AssessmentType.HIPPS;
import static gov.cms.grouper.snf.model.AssessmentType.NON_THERAPY;
import static gov.cms.grouper.snf.model.AssessmentType.NURSING;
import static gov.cms.grouper.snf.model.AssessmentType.OBRA;
import static gov.cms.grouper.snf.model.AssessmentType.PDX;
import static gov.cms.grouper.snf.model.AssessmentType.PPS;
import static gov.cms.grouper.snf.model.AssessmentType.PROCEDURE_MAJOR;
import static gov.cms.grouper.snf.model.AssessmentType.PROCEDURE_NON_ORTHOPEDIC;
import static gov.cms.grouper.snf.model.AssessmentType.PROCEDURE_ORTHOPEDIC;
import static gov.cms.grouper.snf.model.AssessmentType.SERVICES;
import static gov.cms.grouper.snf.model.AssessmentType.SPEECH;
import static gov.cms.grouper.snf.model.AssessmentType.SURGERY;
import static gov.cms.grouper.snf.model.AssessmentType.SWALLOWING;

import gov.cms.grouper.snf.model.AssessmentType;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Provides enums for the Assessment Types with their location in a flat file and valid values.
 * Valid values format: first two as its range, and following as its acceptable values.
 */
public enum Rai300 implements AssessmentItem {
  A0310A(270, 2, "A0310A", OBRA, false, false, 1, 2, 3, 4, 5, 6, 99),
  A0310B(272, 2, "A0310B", PPS, false, false, 1, 8, 99),
  A2300(486, 8, "A2300", ARD, false, true),
  B0100(511, 1, "B0100", COGNITIVE, true, false, 0, 1),
  B0700(515, 1, "B0700", COGNITIVE, true, true, 0, 1, 2, 3),
  C0100(519, 1, "C0100", NURSING, true, true, 0, 1),
  C0500(527, 2, "C0500", NURSING, true, true, 0, 15, 99),
  C0700(530, 1, "C0700", COGNITIVE, true, true, 0, 1),
  C1000(537, 1, "C1000", COGNITIVE, true, true, 0, 1, 2, 3),
  D0300(562, 2, "D0300", NURSING, true, true, 0, 27, 99),
  D0600(585, 2, "D0600", NURSING, true, true, 0, 30),
  E0100A(588, 1, "E0100A", NURSING, true, true, 0, 1),
  E0100B(589, 1, "E0100B", NURSING, true, true, 0, 1),
  E0200A(591, 1, "E0200A", NURSING, true, true, 0, 1, 2, 3),
  E0200B(592, 1, "E0200B", NURSING, true, true, 0, 1, 2, 3),
  E0200C(593, 1, "E0200C", NURSING, true, true, 0, 1, 2, 3),
  E0800(601, 1, "E0800", NURSING, true, true, 0, 1, 2, 3),
  E0900(602, 1, "E0900", NURSING, true, true, 0, 1, 2, 3),
  H0100C(684, 1, "H0100C", NON_THERAPY, true, false, 0, 1),
  H0100D(685, 1, "H0100D", NON_THERAPY, true, false, 0, 1),
  H0200C(689, 1, "H0200C", NURSING, true, true, 0, 1),
  H0500(692, 1, "H0500", NURSING, true, false, 0, 1),
  I1300(705, 1, "I1300", NON_THERAPY, true, false, 0, 1),
  I1700(710, 1, "I1700", NON_THERAPY, true, false, 0, 1),
  I2000(711, 1, "I2000", NURSING, true, false, 0, 1),
  I2100(712, 1, "I2100", NURSING, true, false, 0, 1),
  I2500(716, 1, "I2500", NON_THERAPY, true, false, 0, 1),
  I2900(717, 1, "I2900", NON_THERAPY, true, false, 0, 1),
  I4300(727, 1, "I4300", SPEECH, true, false, 0, 1),
  I4400(728, 1, "I4400", NURSING, true, false, 0, 1),
  I4500(729, 1, "I4500", SPEECH, true, false, 0, 1),
  I4900(731, 1, "I4900", SPEECH, true, false, 0, 1),
  I5100(733, 1, "I5100", NURSING, true, false, 0, 1),
  I5200(734, 1, "I5200", NON_THERAPY, true, false, 0, 1),
  I5300(736, 1, "I5300", NURSING, true, false, 0, 1),
  I5500(739, 1, "I5500", SPEECH, true, false, 0, 1),
  I5600(740, 1, "I5600", NON_THERAPY, true, false, 0, 1),
  I6200(747, 1, "I6200", NON_THERAPY, true, false, 0, 1),
  I6300(748, 1, "I6300", NURSING, true, false, 0, 1),
  I8000A(751, 8, "I8000A", SERVICES, true, true),
  I8000B(759, 8, "I8000B", SERVICES, true, true),
  I8000C(767, 8, "I8000C", SERVICES, true, true),
  I8000D(775, 8, "I8000D", SERVICES, true, true),
  I8000E(783, 8, "I8000E", SERVICES, true, true),
  I8000F(791, 8, "I8000F", SERVICES, true, true),
  I8000G(799, 8, "I8000G", SERVICES, true, true),
  I8000H(807, 8, "I8000H", SERVICES, true, true),
  I8000I(815, 8, "I8000I", SERVICES, true, true),
  I8000J(823, 8, "I8000J", SERVICES, true, true),
  J1100C(851, 1, "J1100C", NURSING, true, false, 0, 1),
  J1550A(855, 1, "J1550A", NURSING, true, false, 0, 1),
  J1550B(856, 1, "J1550B", NURSING, true, false, 0, 1),
  K0100A(867, 1, "K0100A", SWALLOWING, true, false, 0, 1),
  K0100B(868, 1, "K0100B", SWALLOWING, true, false, 0, 1),
  K0100C(869, 1, "K0100C", SWALLOWING, true, false, 0, 1),
  K0100D(870, 1, "K0100D", SWALLOWING, true, false, 0, 1),
  K0300(877, 1, "K0300", NURSING, true, false, 0, 1, 2),
  M0300B1(900, 1, "M0300B1", NURSING, true, true, 0, 9),
  M0300C1(910, 1, "M0300C1", NURSING, true, true, 0, 9),
  M0300D1(912, 1, "M0300D1", NON_THERAPY, true, true, 0, 9),
  M0300F1(916, 1, "M0300F1", NURSING, true, true, 0, 9),
  M1030(940, 1, "M1030", NURSING, true, false, 0, 9),
  M1040A(941, 1, "M1040A", NON_THERAPY, true, false, 0, 1),
  M1040B(942, 1, "M1040B", NON_THERAPY, true, false, 0, 1),
  M1040C(943, 1, "M1040C", NON_THERAPY, true, false, 0, 1),
  M1040D(944, 1, "M1040D", NURSING, true, false, 0, 1),
  M1040E(945, 1, "M1040E", NURSING, true, false, 0, 1),
  M1040F(946, 1, "M1040F", NURSING, true, false, 0, 1),
  M1200A(948, 1, "M1200A", NURSING, true, false, 0, 1),
  M1200B(949, 1, "M1200B", NURSING, true, false, 0, 1),
  M1200C(950, 1, "M1200C", NURSING, true, false, 0, 1),
  M1200D(951, 1, "M1200D", NURSING, true, false, 0, 1),
  M1200E(952, 1, "M1200E", NURSING, true, false, 0, 1),
  M1200F(953, 1, "M1200F", NURSING, true, false, 0, 1),
  M1200G(954, 1, "M1200G", NURSING, true, false, 0, 1),
  M1200H(955, 1, "M1200H", NURSING, true, false, 0, 1),
  M1200I(956, 1, "M1200I", NURSING, true, false, 0, 1),
  N0350A(959, 1, "N0350A", NURSING, true, true, 0, 7),
  N0350B(960, 1, "N0350B", NURSING, true, true, 0, 7),
  O0100A2(970, 1, "O0100A2", NURSING, true, false, 0, 1),
  O0100B2(972, 1, "O0100B2", NON_THERAPY, true, false, 0, 1),
  O0100C2(974, 1, "O0100C2", NURSING, true, false, 0, 1),
  O0100D2(976, 1, "O0100D2", NON_THERAPY, true, false, 0, 1),
  O0100E2(978, 1, "O0100E2", SPEECH, true, false, 0, 1),
  O0100F2(980, 1, "O0100F2", SPEECH, true, false, 0, 1),
  O0100H2(984, 1, "O0100H2", NON_THERAPY, true, false, 0, 1),
  O0100I2(986, 1, "O0100I2", NON_THERAPY, true, false, 0, 1),
  O0100J2(988, 1, "O0100J2", NURSING, true, false, 0, 1),
  O0100M2(993, 1, "O0100M2", NON_THERAPY, true, false, 0, 1),
  O0400D2(1099, 1, "O0400D2", NURSING, true, true, 0, 7),
  O0500A(1110, 1, "O0500A", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),
  O0500B(1111, 1, "O0500B", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),
  O0500C(1112, 1, "O0500C", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),
  O0500D(1113, 1, "O0500D", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),
  O0500E(1114, 1, "O0500E", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),
  O0500F(1115, 1, "O0500F", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),
  O0500G(1116, 1, "O0500G", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),
  O0500H(1117, 1, "O0500H", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),
  O0500I(1118, 1, "O0500I", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),
  O0500J(1119, 1, "O0500J", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),
  Z0100A(1344, 7, "Z0100A", HIPPS, false, true),
  K0510A1(1444, 1, "K0510A1", NURSING, true, true, 0, 1),
  K0510A2(1445, 1, "K0510A2", NON_THERAPY, true, false, 0, 1),
  K0510B1(1446, 1, "K0510B1", NURSING, true, true, 0, 1),
  K0510B2(1447, 1, "K0510B2", NON_THERAPY, true, false, 0, 1),
  K0510C2(1449, 1, "K0510C2", DIET_MECHANICAL, true, true, 0, 1),
  K0710A2(1467, 1, "K0710A2", NON_THERAPY, true, true, 1, 2, 3),
  K0710A3(1468, 1, "K0710A3", NURSING, true, true, 1, 2, 3),
  K0710B2(1470, 1, "K0710B2", NON_THERAPY, true, true, 1, 2),
  K0710B3(1471, 1, "K0710B3", NURSING, true, true, 1, 2),
  GG0130A1(1498, 2, "GG0130A1", FUNCTIONAL_EATING, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 88, 10),
  GG0130B1(1504, 2, "GG0130B1", FUNCTIONAL_HYGIENE_ORAL, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 88,
      10),
  GG0130C1(1510, 2, "GG0130C1", FUNCTIONAL_HYGIENE_TOILET, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 88,
      10),
  GG0170B1(1516, 2, "GG0170B1", FUNCTIONAL_BED_MOBILITY_TO_LYING, true, true, 6, 5, 4, 3, 2, 1, 7,
      9, 88, 10),
  GG0170C1(1522, 2, "GG0170C1", FUNCTIONAL_BED_MOBILITY_TO_SITTING, true, true, 6, 5, 4, 3, 2, 1, 7,
      9, 88, 10),
  GG0170D1(1528, 2, "GG0170D1", FUNCTIONAL_TRANSFER_TO_STANDING, true, true, 6, 5, 4, 3, 2, 1, 7, 9,
      88, 10),
  GG0170E1(1534, 2, "GG0170E1", FUNCTIONAL_TRANSFER_CHAIR, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 88,
      10),
  GG0170F1(1540, 2, "GG0170F1", FUNCTIONAL_TRANSFER_TOILET, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 88,
      10),
  GG0170J1(1548, 2, "GG0170J1", FUNCTIONAL_WALKING_50_FEET, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 88,
      10),
  GG0170K1(1554, 2, "GG0170K1", FUNCTIONAL_WALKING_150_FEET, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 88,
      10),
  GG0130A5(1704, 2, "GG0130A5", FUNCTIONAL_EATING_IPA, true, false, 6, 5, 4, 3, 2, 1, 7, 9, 10, 88),
  GG0130B5(1706, 2, "GG0130B5", FUNCTIONAL_HYGIENE_ORAL_IPA, true, false, 6, 5, 4, 3, 2, 1, 7, 9,
      10, 88),
  GG0130C5(1708, 2, "GG0130C5", FUNCTIONAL_HYGIENE_TOILET_IPA, true, false, 6, 5, 4, 3, 2, 1, 7, 9,
      10, 88),
  GG0170B5(1710, 2, "GG0170B5", FUNCTIONAL_BED_MOBILITY_TO_LYING_IPA, true, false, 6, 5, 4, 3, 2, 1,
      7, 9, 10, 88),
  GG0170C5(1712, 2, "GG0170C5", FUNCTIONAL_BED_MOBILITY_TO_SITTING_IPA, true, false, 6, 5, 4, 3, 2,
      1, 7, 9, 10, 88),
  GG0170D5(1714, 2, "GG0170D5", FUNCTIONAL_TRANSFER_TO_STANDING_IPA, true, false, 6, 5, 4, 3, 2, 1,
      7, 9, 10, 88),
  GG0170E5(1716, 2, "GG0170E5", FUNCTIONAL_TRANSFER_CHAIR_IPA, true, false, 6, 5, 4, 3, 2, 1, 7, 9,
      10, 88),
  GG0170F5(1718, 2, "GG0170F5", FUNCTIONAL_TRANSFER_TOILET_IPA, true, false, 6, 5, 4, 3, 2, 1, 7, 9,
      10, 88),
  GG0170J5(1722, 2, "GG0170J5", FUNCTIONAL_WALKING_50_FEET_IPA, true, true, 6, 5, 4, 3, 2, 1, 7, 9,
      10, 88),
  GG0170K5(1724, 2, "GG0170K5", FUNCTIONAL_WALKING_150_FEET_IPA, true, true, 6, 5, 4, 3, 2, 1, 7, 9,
      10, 88),
  I0020B(1726, 8, "I0020B", PDX, true, true),
  J2100(1734, 1, "J2100", SURGERY, false, true, 0, 1, 8),
  J2300(1735, 1, "J2300", PROCEDURE_MAJOR, false, true, 0, 1),
  J2310(1736, 1, "J2310", PROCEDURE_MAJOR, false, true, 0, 1),
  J2320(1737, 1, "J2320", PROCEDURE_MAJOR, false, true, 0, 1),
  J2330(1738, 1, "J2330", PROCEDURE_MAJOR, false, true, 0, 1),
  J2400(1739, 1, "J2400", PROCEDURE_MAJOR, false, true, 0, 1),
  J2410(1740, 1, "J2410", PROCEDURE_MAJOR, false, true, 0, 1),
  J2420(1741, 1, "J2420", PROCEDURE_MAJOR, false, true, 0, 1),
  J2500(1743, 1, "J2500", PROCEDURE_ORTHOPEDIC, false, true, 0, 1),
  J2510(1744, 1, "J2510", PROCEDURE_ORTHOPEDIC, false, true, 0, 1),
  J2520(1745, 1, "J2520", PROCEDURE_ORTHOPEDIC, false, true, 0, 1),
  J2530(1746, 1, "J2530", PROCEDURE_ORTHOPEDIC, false, true, 0, 1),
  J2600(1748, 1, "J2600", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),
  J2610(1749, 1, "J2610", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),
  J2620(1750, 1, "J2620", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),
  J2700(1752, 1, "J2700", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),
  J2710(1753, 1, "J2710", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),
  J2800(1755, 1, "J2800", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),
  J2810(1756, 1, "J2810", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),
  J2900(1758, 1, "J2900", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),
  J2910(1759, 1, "J2910", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),
  J2920(1760, 1, "J2920", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),
  J2930(1761, 1, "J2930", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),
  J2940(1762, 1, "J2940", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),
  RECALCULATED_Z0100A(3073, 7, "RECALCULATED_Z0100A", CALCULATED_HIPPS, false, true),
  RECALCULATED_Z0100B(3080, 10, "RECALCULATED_Z0100B", CALCULATED_VERSION, false, true),
  ERROR_REASON(3488, 99, "ERROR_REASON", AssessmentType.ERROR_REASON, true, true);

  public static final int FIXED_LENGTH_SIZE = 3688;

  private final int index;
  private final int length;
  private final String xmlTag;
  private final AssessmentType assessmentType;
  private final boolean blankAllowed;
  private final boolean notAssessedAllowed;
  private final List<Integer> validValues;

  Rai300(int index, int length, String xmlTag, AssessmentType assessmentType,
      boolean notAssessedAllowed, boolean blankAllowed, int... validValues) {
    this.index = index;
    this.length = length;
    this.xmlTag = xmlTag;
    this.assessmentType = assessmentType;
    this.blankAllowed = blankAllowed;
    this.notAssessedAllowed = notAssessedAllowed;
    this.validValues = Arrays.stream(validValues).boxed().collect(Collectors.toList());
  }

  public static Set<Rai300> getAssessmentsByType(AssessmentType assessmentType) {
    Set<Rai300> assessments = new HashSet<>();
    for (Rai300 rai300 : Rai300.values()) {
      if (rai300.getAssessmentType() == assessmentType) {
        assessments.add(rai300);
      }
    }
    return assessments;
  }

  @Override
  public int getIndex() {
    return this.index;
  }

  @Override
  public int getLength() {
    return this.length;
  }

  @Override
  public String getXmlTag() {
    return this.xmlTag;
  }

  @Override
  public AssessmentType getAssessmentType() {
    return this.assessmentType;
  }

  @Override
  public boolean isBlankAllowed() {
    return this.blankAllowed;
  }

  @Override
  public boolean isNotAssessedAllowed() {
    return this.notAssessedAllowed;
  }

  @Override
  public List<Integer> getValidValues() {
    return this.validValues;
  }

  @Override
  public Rai300[] getEnumValues() {
    return Rai300.values();
  }

}
