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

import java.util.*;
import java.util.stream.Collectors;

import static gov.cms.grouper.snf.model.enums.AssessmentType.*;

/**
 * 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 {

  // SECTION A: IDENTIFICATION INFORMATION

  /** Type of assessment: OBRA */
  // 01. Admission assessment (required by day 14)
  // 02. Quarterly review assessment
  // 03. Annual assessment
  // 04. Significant change in status assessment
  // 05. Significant correction to prior comprehensive assessment
  // 06. Significant correction to prior quarterly assessment
  // 99. None of the above
  A0310A(270, 2, "A0310A", OBRA, false, false, 1, 2, 3, 4, 5, 6, 99),

  /** Type of assessment: PPS */
  // 01. 5-day scheduled assessment
  // 08. IPA - Interim Payment Assessment
  // 99. None of the Above
  A0310B(272, 2, "A0310B", PPS, false, false, 1, 8, 99),

  /** Assessment reference date */
  // YYYYMMDD
  A2300(486, 8, "A2300", ARD, false, true),

  // SECTION B: HEARING, SPEECH, AND VISION

  /** Comatose */
  B0100(511, 1, "B0100", COGNITIVE, true, false, 0, 1),

  /** Makes self understood */
  B0700(515, 1, "B0700", COGNITIVE, true, true, 0, 1, 2, 3),

  // SECTION C: COGNITIVE PATTERNS

  /** BIMS: should resident interview be conducted */
  C0100(519, 1, "C0100", NURSING, true, true, 0, 1),

  /** BIMS res interview: summary score */
  C0500(527, 2, "C0500", NURSING, true, true, 0, 15, 99),

  /** Staff assessment mental status: short-term memory OK */
  C0700(530, 1, "C0700", COGNITIVE, true, true, 0, 1),

  /** Cognitive skills for daily decision making */
  C1000(537, 1, "C1000", COGNITIVE, true, true, 0, 1, 2, 3),

  // SECTION D: MOOD
  /** PHQ res: total mood severity score (retired)*/
  D0300(562, 2, "D0300", NURSING, true, true, 0, 27, 99),

  /** PHQ res: total mood severity score */
  D0160(1908, 2, "D0160", NURSING, true, true, 0, 27, 99),

  /** PHQ staff: total mood severity score */
  D0600(585, 2, "D0600", NURSING, true, true, 0, 30),

  // SECTION E: BEHAVIOR

  /** Psychosis: hallucinations */
  E0100A(588, 1, "E0100A", NURSING, true, true, 0, 1),

  /** Psychosis: delusions */
  E0100B(589, 1, "E0100B", NURSING, true, true, 0, 1),

  /** Physical behavioral symptoms directed toward others */
  E0200A(591, 1, "E0200A", NURSING, true, true, 0, 1, 2, 3),

  /** Verbal behavioral symptoms directed toward others */
  E0200B(592, 1, "E0200B", NURSING, true, true, 0, 1, 2, 3),

  /** Other behavioral symptoms not directed toward others */
  E0200C(593, 1, "E0200C", NURSING, true, true, 0, 1, 2, 3),

  /** Rejection of care: presence and frequency */
  E0800(601, 1, "E0800", NURSING, true, true, 0, 1, 2, 3),

  /** Wandering: presence and frequency */
  E0900(602, 1, "E0900", NURSING, true, true, 0, 1, 2, 3),

  // SECTION H: BLADDER AND BOWEL

  /** Appliances: ostomy */
  H0100C(684, 1, "H0100C", NON_THERAPY, true, false, 0, 1),

  /** Appliances: intermittent catheterization */
  H0100D(685, 1, "H0100D", NON_THERAPY, true, false, 0, 1),

  /** Urinary toileting program: current program/trial */
  H0200C(689, 1, "H0200C", NURSING, true, true, 0, 1),

  /** Bowel toileting program being used */
  H0500(692, 1, "H0500", NURSING, true, false, 0, 1),

  // SECTION I: ACTIVE DIAGNOSES

  /** Ulcerative colitis, Crohn's, inflammatory bowel disease */
  I1300(705, 1, "I1300", NON_THERAPY, true, false, 0, 1),

  /** Multidrug-resistant organism (MDRO) */
  I1700(710, 1, "I1700", NON_THERAPY, true, false, 0, 1),

  /** Pneumonia */
  I2000(711, 1, "I2000", NURSING, true, false, 0, 1),

  /** Septicemia */
  I2100(712, 1, "I2100", NURSING, true, false, 0, 1),

  /** Wound infection (other than foot) */
  I2500(716, 1, "I2500", NON_THERAPY, true, false, 0, 1),

  /** Diabetes mellitus (DM) */
  I2900(717, 1, "I2900", NON_THERAPY, true, false, 0, 1),

  /** Aphasia */
  I4300(727, 1, "I4300", SPEECH, true, false, 0, 1),

  /** Cerebral palsy */
  I4400(728, 1, "I4400", NURSING, true, false, 0, 1),

  /** Cerebrovascular accident (CVA), TIA, or stroke */
  I4500(729, 1, "I4500", SPEECH, true, false, 0, 1),

  /** Hemiplegia or hemiparesis */
  I4900(731, 1, "I4900", SPEECH, true, false, 0, 1),

  /** Quadriplegia */
  I5100(733, 1, "I5100", NURSING, true, false, 0, 1),

  /** Multiple sclerosis */
  I5200(734, 1, "I5200", NON_THERAPY, true, false, 0, 1),

  /** Parkinson's disease */
  I5300(736, 1, "I5300", NURSING, true, false, 0, 1),

  /** Traumatic brain injury (TBI) */
  I5500(739, 1, "I5500", SPEECH, true, false, 0, 1),

  /** Malnutrition (protein, calorie), risk of malnutrition */
  I5600(740, 1, "I5600", NON_THERAPY, true, false, 0, 1),

  /** Asthma, COPD, or chronic lung disease */
  I6200(747, 1, "I6200", NON_THERAPY, true, false, 0, 1),

  /** Respiratory failure */
  I6300(748, 1, "I6300", NURSING, true, false, 0, 1),

  /** Additional active ICD diagnosis */
  I8000A(751, 8, "I8000A", SERVICES, true, true),

  /** Additional active ICD diagnosis */
  I8000B(759, 8, "I8000B", SERVICES, true, true),

  /** Additional active ICD diagnosis */
  I8000C(767, 8, "I8000C", SERVICES, true, true),

  /** Additional active ICD diagnosis */
  I8000D(775, 8, "I8000D", SERVICES, true, true),

  /** Additional active ICD diagnosis */
  I8000E(783, 8, "I8000E", SERVICES, true, true),

  /** Additional active ICD diagnosis */
  I8000F(791, 8, "I8000F", SERVICES, true, true),

  /** Additional active ICD diagnosis */
  I8000G(799, 8, "I8000G", SERVICES, true, true),

  /** Additional active ICD diagnosis */
  I8000H(807, 8, "I8000H", SERVICES, true, true),

  /** Additional active ICD diagnosis */
  I8000I(815, 8, "I8000I", SERVICES, true, true),

  /** Additional active ICD diagnosis 10 */
  I8000J(823, 8, "I8000J", SERVICES, true, true),

  // SECTION J: HEALTH CONDITIONS

  /** Short breath/trouble breathing: lying flat */
  J1100C(851, 1, "J1100C", NURSING, true, false, 0, 1),

  /** Problem conditions: fever */
  J1550A(855, 1, "J1550A", NURSING, true, false, 0, 1),

  /** Problem conditions: vomiting */
  J1550B(856, 1, "J1550B", NURSING, true, false, 0, 1),

  // SECTION K: SWALLOWING/NUTRITIONAL STATUS

  /** Swallow disorder: loss liquids/solids from mouth */
  K0100A(867, 1, "K0100A", SWALLOWING, true, false, 0, 1),

  /** Swallow disorder: holds food in mouth/cheeks */
  K0100B(868, 1, "K0100B", SWALLOWING, true, false, 0, 1),

  /** Swallow disorder: cough/choke with meals/meds */
  K0100C(869, 1, "K0100C", SWALLOWING, true, false, 0, 1),

  /** Swallow disorder: difficulty or pain swallowing */
  K0100D(870, 1, "K0100D", SWALLOWING, true, false, 0, 1),

  /** Weight loss */
  K0300(877, 1, "K0300", NURSING, true, false, 0, 1, 2),

  // SECTION M: SKIN CONDITIONS

  /** Stage 2 pressure ulcers: number present */
  M0300B1(900, 1, "M0300B1", NURSING, true, true, 0, 9),

  /** Stage 3 pressure ulcers: number present */
  M0300C1(910, 1, "M0300C1", NURSING, true, true, 0, 9),

  /** Stage 4 pressure ulcers: number present */
  M0300D1(912, 1, "M0300D1", NON_THERAPY, true, true, 0, 9),

  /** Unstaged slough/eschar: number present */
  M0300F1(916, 1, "M0300F1", NURSING, true, true, 0, 9),

  /** Number of venous and arterial ulcer */
  M1030(940, 1, "M1030", NURSING, true, false, 0, 9),

  /** Other skin problems: infection of the foot */
  M1040A(941, 1, "M1040A", NON_THERAPY, true, false, 0, 1),

  /** Other skin problems: diabetic foot ulcer(s) */
  M1040B(942, 1, "M1040B", NON_THERAPY, true, false, 0, 1),

  /** Other skin problems: other open lesion(s) on the foot */
  M1040C(943, 1, "M1040C", NON_THERAPY, true, false, 0, 1),

  /** Other skin problems: lesions not ulcers, rashes, cut */
  M1040D(944, 1, "M1040D", NURSING, true, false, 0, 1),

  /** Other skin problems: surgical wound(s) */
  M1040E(945, 1, "M1040E", NURSING, true, false, 0, 1),

  /** Other skin problems: burns (second or third degree) */
  M1040F(946, 1, "M1040F", NURSING, true, false, 0, 1),

  /** Skin/ulcer treatments: pressure reducing device for chair */
  M1200A(948, 1, "M1200A", NURSING, true, false, 0, 1),

  /** Skin/ulcer treatments: pressure reducing device for bed */
  M1200B(949, 1, "M1200B", NURSING, true, false, 0, 1),

  /** Skin/ulcer treatments: turning/repositioning */
  M1200C(950, 1, "M1200C", NURSING, true, false, 0, 1),

  /** Skin/ulcer treatments: nutrition/hydration */
  M1200D(951, 1, "M1200D", NURSING, true, false, 0, 1),

  /** Skin/ulcer treatments: pressure ulcer/injury care */
  M1200E(952, 1, "M1200E", NURSING, true, false, 0, 1),

  /** Skin/ulcer treatments: surgical wound care */
  M1200F(953, 1, "M1200F", NURSING, true, false, 0, 1),

  /** Skin/ulcer treatments: application of dressing */
  M1200G(954, 1, "M1200G", NURSING, true, false, 0, 1),

  /** Skin/ulcer treatments: apply ointments/medication */
  M1200H(955, 1, "M1200H", NURSING, true, false, 0, 1),

  /** Skin/ulcer treatments: apply dressings to feet */
  M1200I(956, 1, "M1200I", NURSING, true, false, 0, 1),

  // SECTION N: MEDICATIONS

  /** Insulin: insulin injections */
  N0350A(959, 1, "N0350A", NURSING, true, true, 0, 7),

  /** Insulin: orders for insulin */
  N0350B(960, 1, "N0350B", NURSING, true, true, 0, 7),

  // SECTION O: SPECIAL TREATMENTS, PROCEDURES, AND PROGRAMS

  /** Treatment: chemotherapy - while resident (retired)*/
  O0100A2(970, 1, "O0100A2", NURSING, true, false, 0, 1),

  /** Treatment: chemotherapy - while resident */
  O0110A1B(3364, 1, "O0110A1b", NURSING, true, false, 0, 1),

  /** Treatment: radiation - while resident (retired)*/
  O0100B2(972, 1, "O0100B2", NON_THERAPY, true, false, 0, 1),

  /** Treatment: radiation - while resident */
  O0110B1B(3371, 1, "O0110B1b", NON_THERAPY, true, false, 0, 1),

  /** Treatment: oxygen therapy - while resident (retired)*/
  O0100C2(974, 1, "O0100C2", NURSING, true, false, 0, 1),

  /** Treatment: oxygen therapy - while resident */
  O0110C1B(3374, 1, "O0110C1b", NURSING, true, false, 0, 1),

  /** Treatment: suctioning - while resident (retired)*/
  O0100D2(976, 1, "O0100D2", NON_THERAPY, true, false, 0, 1),

  /** Treatment: suctioning - while resident */
  O0110D1B(3383, 1, "O0110D1b", NON_THERAPY, true, false, 0, 1),

  /** Treatment: tracheostomy care - while resident (retired)*/
  O0100E2(978, 1, "O0100E2", SPEECH, true, false, 0, 1),

  /** Treatment: tracheostomy care - while resident */
  O0110E1B(3390, 1, "O0110E1b", SPEECH, true, false, 0, 1),

  /** Invasive Mechanical Ventilator (ventilator or respirator) - while a resident (retired)*/
  O0100F2(980, 1, "O0100F2", SPEECH, true, false, 0, 1),

  /** Invasive Mechanical Ventilator (ventilator or respirator) - while a resident */
  O0110F1B(3393, 1, "O0110F1b", SPEECH, true, false, 0, 1),

  /** Treatment: IV medications - while resident (retired)*/
  O0100H2(984, 1, "O0100H2", NON_THERAPY, true, false, 0, 1),

  /** Treatment: IV medications - while resident */
  O0110H1B(3405, 1, "O0110H1b", NON_THERAPY, true, false, 0, 1),

  /** Treatment: transfusions - while resident (retired)*/
  O0100I2(986, 1, "O0100I2", NON_THERAPY, true, false, 0, 1),

  /** Treatment: transfusions - while resident */
  O0110I1B(3414, 1, "O0110I1b", NON_THERAPY, true, false, 0, 1),

  /** Treatment: dialysis - while resident (retired)*/
  O0100J2(988, 1, "O0100J2", NURSING, true, false, 0, 1),

  /** Treatment: dialysis - while resident */
  O0110J1B(3417, 1, "O0110J1b", NURSING, true, false, 0, 1),

  /** Treatment: isolate/quarantine - while resident (retired)*/
  O0100M2(993, 1, "O0100M2", NON_THERAPY, true, false, 0, 1),

  /** Treatment: isolate/quarantine - while resident */
  O0110M1B(3424, 1, "O0110M1b", NON_THERAPY, true, false, 0, 1),

  /** Respiratory therapy: number of day */
  O0400D2(1099, 1, "O0400D2", NURSING, true, true, 0, 7),

  /** Range of motion (passive): number of days */
  O0500A(1110, 1, "O0500A", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),

  /** Range of motion (active): number of days */
  O0500B(1111, 1, "O0500B", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),

  /** Splint or brace assistance: number of days */
  O0500C(1112, 1, "O0500C", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),

  /** Bed mobility training: number of days */
  O0500D(1113, 1, "O0500D", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),

  /** Transfer training: number of days */
  O0500E(1114, 1, "O0500E", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),

  /** Walking training: number of days */
  O0500F(1115, 1, "O0500F", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),

  /** Dressing and/or grooming training: number of days */
  O0500G(1116, 1, "O0500G", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),

  /** Eating and/or swallowing training: number of days */
  O0500H(1117, 1, "O0500H", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),

  /** Amputation/prosthesis training: number of day */
  O0500I(1118, 1, "O0500I", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),

  /** Communication training: number of days */
  O0500J(1119, 1, "O0500J", NURSING, true, false, 0, 1, 2, 3, 4, 5, 6, 7),

  // SECTION Z: ASSESSMENT ADMINISTRATION

  /** Medicare Part A: HIPPS code */
  Z0100A(1344, 7, "Z0100A", HIPPS, false, true),

  // SECTION K: SWALLOWING/NUTRITIONAL STATUS (cont.)
  /** Nutritional approaches: Not Res: parenteral/IV feeding - while not a resident (retired)*/
  K0510A1(1444, 1, "K0510A1", NURSING, true, true, 0, 1),

  /** Nutritional approaches: Not Res: parenteral/IV feeding - while not a resident */
  K0520A2(3323, 1, "K0520A2", NURSING, true, true, 0, 1),

  /** Nutritional approaches: Res: parenteral/IV feeding - while a resident (retired)*/
  K0510A2(1445, 1, "K0510A2", NON_THERAPY, true, false, 0, 1),

  /** Nutritional approaches: Res: parenteral/IV feeding - while a resident */
  K0520A3(3324, 1, "K0520A3", NON_THERAPY, true, false, 0, 1),

  /** Nutritional approaches: Not Res: feeding tube - while not a resident (retired)*/
  K0510B1(1446, 1, "K0510B1", NURSING, true, true, 0, 1),

  /** Nutritional approaches: Not Res: feeding tube - while not a resident*/
  K0520B2(3327, 1, "K0520B2", NURSING, true, true, 0, 1),

  /** Nutritional approaches: Res: feeding tube - while a resident (retired)*/
  K0510B2(1447, 1, "K0510B2", NON_THERAPY, true, false, 0, 1),

  /** Nutritional approaches: Res: feeding tube - while a resident */
  K0520B3(3328, 1, "K0520B3", NON_THERAPY, true, false, 0, 1),

  /** Nutritional approaches: Res: mechanically altered diet - while a resident (retired)*/
  K0510C2(1449, 1, "K0510C2", DIET_MECHANICAL, true, true, 0, 1),

  /** Nutritional approaches: Res: mechanically altered diet - while a resident */
  K0520C3(3331, 1, "K0520C3", DIET_MECHANICAL, true, false, 0, 1),

  /** Prop calories parenteral/tube feed: while a resident */
  K0710A2(1467, 1, "K0710A2", NON_THERAPY, true, true, 1, 2, 3),

  /** Prop calories parenteral/tube feed: 7 day */
  K0710A3(1468, 1, "K0710A3", NURSING, true, true, 1, 2, 3),

  /** Avg fluid intake per day IV/ tube: while a resident */
  K0710B2(1470, 1, "K0710B2", NON_THERAPY, true, true, 1, 2),

  /** Avg fluid intake per day IV/tube: 7 day */
  K0710B3(1471, 1, "K0710B3", NURSING, true, true, 1, 2),

  // SECTION GG: FUNCTIONAL ABILITIES AND GOALS

  /** Eating (Admission Performance) */
  GG0130A1(1498, 2, "GG0130A1", FUNCTIONAL_EATING, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 88, 10),

  /** Oral Hygiene (Admission Performance) */
  GG0130B1(1504, 2, "GG0130B1", FUNCTIONAL_HYGIENE_ORAL, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 88, 10),

  /** Toileting Hygiene (Admission Performance) */
  GG0130C1(1510, 2, "GG0130C1", FUNCTIONAL_HYGIENE_TOILET, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 88, 10),

  /** Sit to lying (Admission Performance) */
  GG0170B1(1516, 2, "GG0170B1", FUNCTIONAL_BED_MOBILITY_TO_LYING, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 88, 10),

  /** Lying to sitting on bed side (Admission  Performance) */
  GG0170C1(1522, 2, "GG0170C1", FUNCTIONAL_BED_MOBILITY_TO_SITTING, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 88, 10),

  /** Sit to stand (Admission Performance) */
  GG0170D1(1528, 2, "GG0170D1", FUNCTIONAL_TRANSFER_TO_STANDING, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 88, 10),

  /** Chair/bed-to-chair transfer (Admission  Performance) */
  GG0170E1(1534, 2, "GG0170E1", FUNCTIONAL_TRANSFER_CHAIR, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 88, 10),

  /** Toilet transfer (Admission Performance) */
  GG0170F1(1540, 2, "GG0170F1", FUNCTIONAL_TRANSFER_TOILET, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 88, 10),

  /** Walk 50 feet with two turns (Admission  Performance) */
  GG0170J1(1548, 2, "GG0170J1", FUNCTIONAL_WALKING_50_FEET, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 88, 10),

  /** Walk 150 feet (Admission Performance) */
  GG0170K1(1554, 2, "GG0170K1", FUNCTIONAL_WALKING_150_FEET, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 88, 10),

  /** Eating (Interim Performance) */
  GG0130A5(1704, 2, "GG0130A5", FUNCTIONAL_EATING_IPA, true, false, 6, 5, 4, 3, 2, 1, 7, 9, 10, 88),

  /** Oral Hygiene (Interim Performance) */
  GG0130B5(1706, 2, "GG0130B5", FUNCTIONAL_HYGIENE_ORAL_IPA, true, false, 6, 5, 4, 3, 2, 1, 7, 9, 10, 88),

  /** Toileting Hygiene (Interim Performance) */
  GG0130C5(1708, 2, "GG0130C5", FUNCTIONAL_HYGIENE_TOILET_IPA, true, false, 6, 5, 4, 3, 2, 1, 7, 9, 10, 88),

  /** Sit to lying (Interim Performance) */
  GG0170B5(1710, 2, "GG0170B5", FUNCTIONAL_BED_MOBILITY_TO_LYING_IPA, true, false, 6, 5, 4, 3, 2, 1, 7, 9, 10, 88),

  /** Lying to sitting on bed side (Interim Performance) */
  GG0170C5(1712, 2, "GG0170C5", FUNCTIONAL_BED_MOBILITY_TO_SITTING_IPA, true, false, 6, 5, 4, 3, 2, 1, 7, 9, 10, 88),

  /** Sit to stand (Interim Performance) */
  GG0170D5(1714, 2, "GG0170D5", FUNCTIONAL_TRANSFER_TO_STANDING_IPA, true, false, 6, 5, 4, 3, 2, 1, 7, 9, 10, 88),

  /** Chair/bed-to-chair transfer (Interim Performance) */
  GG0170E5(1716, 2, "GG0170E5", FUNCTIONAL_TRANSFER_CHAIR_IPA, true, false, 6, 5, 4, 3, 2, 1, 7, 9, 10, 88),

  /** Toilet transfer (Interim Performance) */
  GG0170F5(1718, 2, "GG0170F5", FUNCTIONAL_TRANSFER_TOILET_IPA, true, false, 6, 5, 4, 3, 2, 1, 7, 9, 10, 88),

  /** Walk 50 feet with two turns (Interim Performance) */
  GG0170J5(1722, 2, "GG0170J5", FUNCTIONAL_WALKING_50_FEET_IPA, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 10, 88),

  /** Walk 150 feet (Interim Performance) */
  GG0170K5(1724, 2, "GG0170K5", FUNCTIONAL_WALKING_150_FEET_IPA, true, true, 6, 5, 4, 3, 2, 1, 7, 9, 10, 88),

  // SECTION I: ACTIVE DIAGNOSES (cont.)

  /** ICD Code 1 - 13 */
  I0020B(1726, 8, "I0020B", PDX, true, true),

  // SECTION J: HEALTH CONDITIONS (cont.)

  /** Recent Surgery Requiring Active SNF Care */
  J2100(1734, 1, "J2100", SURGERY, false, true, 0, 1, 8),

  /** Knee Replacement - partial or total */
  J2300(1735, 1, "J2300", PROCEDURE_MAJOR, false, true, 0, 1),

  /** Hip Replacement - partial or total */
  J2310(1736, 1, "J2310", PROCEDURE_MAJOR, false, true, 0, 1),

  /** Ankle Replacement - partial or total */
  J2320(1737, 1, "J2320", PROCEDURE_MAJOR, false, true, 0, 1),

  /** Shoulder Replacement - partial or total */
  J2330(1738, 1, "J2330", PROCEDURE_MAJOR, false, true, 0, 1),

  /** Spinal surgery - spinal cord or major spinal nerves */
  J2400(1739, 1, "J2400", PROCEDURE_MAJOR, false, true, 0, 1),

  /** Spinal surgery - fusion of spinal bones */
  J2410(1740, 1, "J2410", PROCEDURE_MAJOR, false, true, 0, 1),

  /** Spinal surgery - lamina, discs, or facets */
  J2420(1741, 1, "J2420", PROCEDURE_MAJOR, false, true, 0, 1),

  /** Ortho surgery - repair fractures of shoulder or arm */
  J2500(1743, 1, "J2500", PROCEDURE_ORTHOPEDIC, false, true, 0, 1),

  /** Ortho surgery - repair fractures of pelvis, hip, leg, knee, or ankle */
  J2510(1744, 1, "J2510", PROCEDURE_ORTHOPEDIC, false, true, 0, 1),

  /** Ortho surgery - repair but not replace joints */
  J2520(1745, 1, "J2520", PROCEDURE_ORTHOPEDIC, false, true, 0, 1),

  /** Ortho surgery - repair other bones */
  J2530(1746, 1, "J2530", PROCEDURE_ORTHOPEDIC, false, true, 0, 1),

  /** Neuro surgery - brain, surrounding tissue or blood vessels */
  J2600(1748, 1, "J2600", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),

  /** Neuro surgery - peripheral and autonomic nervous system - open and percutaneous */
  J2610(1749, 1, "J2610", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),

  /** Neuro surgery - insertion or removal of spinal and brain neurostimulators, electrodes, catheters, and CSF drainage devices */
  J2620(1750, 1, "J2620", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),

  /** Cardiopulmonary surgery - heart or major blood vessels - open and percutaneous procedures */
  J2700(1752, 1, "J2700", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),

  /** Cardiopulmonary surgery - respiratory system, including lungs, bronchi, trachea, larynx, or vocal cords – open and endoscopic */
  J2710(1753, 1, "J2710", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),

  /** Genitourinary surgery - male or female organs */
  J2800(1755, 1, "J2800", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),

  /** Genitourinary surgery - the kidneys, ureter, adrenals, and bladder—open, laparoscopic */
  J2810(1756, 1, "J2810", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),

  /** Major surgery - tendons, ligament, or muscles */
  J2900(1758, 1, "J2900", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),

  /** Major surgery - the GI tract and abdominal contents from the esophagus to the anus, the biliary tree, gall bladder, liver, pancreas, spleen—open or laparoscopic */
  J2910(1759, 1, "J2910", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),

  /** Major surgery - endocrine organs (such as thyroid, parathyroid), neck, lymph nodes, and thymus—open */
  J2920(1760, 1, "J2920", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),

  /** Major surgery - the breast */
  J2930(1761, 1, "J2930", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),

  /** Major surgery - repair of deep ulcers, internal brachytherapy, bone marrow, or stem cell harvest or transplant */
  J2940(1762, 1, "J2940", PROCEDURE_NON_ORTHOPEDIC, false, true, 0, 1),

  // CALC

  /** Medicare Part A: HIPPS code */
  RECALCULATED_Z0100A(3073, 7, "RECALCULATED_Z0100A", CALCULATED_HIPPS, false, true),

  /** Medicare Part A: Version code */
  RECALCULATED_Z0100B(3080, 10, "RECALCULATED_Z0100B", CALCULATED_VERSION, false, true),

  // ERROR

  ERROR_REASON(3488, 99, "ERROR_REASON", AssessmentType.ERROR_REASON, true, true);

  public static final int FIXED_LENGTH_SIZE = 3688;
  public static final int NONE_VALUE = 99;

  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;

  private static final Map<String, Rai300> valueMap = new HashMap<>();

  static {
    for (Rai300 value: values()) {
      valueMap.put(value.name(), value);
    }
  }

  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 = EnumSet.noneOf(Rai300.class);
    for (Rai300 rai300 : Rai300.values()) {
      if (rai300.getAssessmentType() == assessmentType) {
        assessments.add(rai300);
      }
    }
    return assessments;
  }

  public static Set<Rai300> getAssessmentsByTypes(Collection<AssessmentType> types) {
    Set<Rai300> assessments = EnumSet.noneOf(Rai300.class);
    for (Rai300 rai300 : Rai300.values()) {
      if(types.contains(rai300.assessmentType)) assessments.add(rai300);
    }
    return assessments;
  }

  public static Optional<Rai300> of(String value) {
    return Optional.ofNullable(valueMap.get(value));
  }

  public int getIndex() {
    return index;
  }

  public int getLength() {
    return length;
  }

  public String getXmlTag() {
    return xmlTag.toUpperCase();
  }

  public AssessmentType getAssessmentType() {
    return assessmentType;
  }

  public boolean isBlankAllowed() {
    return blankAllowed;
  }

  public boolean isNotAssessedAllowed() {
    return notAssessedAllowed;
  }

  public List<Integer> getValidValues() {
    return validValues;
  }

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

}
