package org.mitre.synthea.export;

import ca.uhn.fhir.parser.IParser;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.hl7.fhir.r4.model.Group;
import org.hl7.fhir.r4.model.Group.GroupType;
import org.hl7.fhir.r4.model.Reference;
import org.mitre.synthea.helpers.Config;
import org.mitre.synthea.helpers.RandomNumberGenerator;

public abstract class FhirGroupExporterR4 {

  private static final List<String> patientList = new ArrayList<String>();

  /**
   * Reset the patient list to empty.
   */
  public static void resetPatientList() {
    patientList.clear();
  }

  /**
   * Add the patient to the patient list.
   * @param resourceId The resource ID of the patient.
   */
  public static synchronized void addPatient(String resourceId) {
    patientList.add(resourceId);
  }

  /**
   * Export the patient list as a FHIR Group resource.
   * @param stop The stop time.
   * @return FHIR Group resource.
   */
  public static Group export(RandomNumberGenerator rand, long stop) {
    String uuid = rand.randUUID().toString();

    Group group = new Group();
    group.setId(uuid);
    group.addIdentifier()
      .setSystem("urn:ietf:rfc:3986")
      .setValue("urn:uuid:" + uuid);
    group.setActive(true);
    group.setType(GroupType.PERSON);
    group.setActual(true);
    group.setName("Synthea Patients");
    group.setQuantity(patientList.size());
    for (String resourceId : patientList) {
      group.addMember().setEntity(new Reference(FhirR4.getUrlPrefix("Patient") + resourceId));
    }
    return group;
  }

  /**
   * Export the current patient list as a FHIR Group resource and save it as a JSON file.
   * @param stop The stop time.
   */
  public static void exportAndSave(RandomNumberGenerator rand, long stop) {
    if (Config.getAsBoolean("exporter.groups.fhir.export")) {
      Group group = export(rand, stop);

      // get output folder
      List<String> folders = new ArrayList<>();
      folders.add("fhir");
      String baseDirectory = Config.get("exporter.baseDirectory");
      File f = Paths.get(baseDirectory, folders.toArray(new String[0])).toFile();
      f.mkdirs();
      Path outFilePath = null;
      String groupJson = null;

      if (Config.getAsBoolean("exporter.fhir.bulk_data")) {
        IParser parser = FhirR4.getContext().newJsonParser().setPrettyPrint(false);
        groupJson = parser.encodeResourceToString(group);
        String filename = group.getResourceType().toString() + ".ndjson";
        outFilePath = f.toPath().resolve(filename);
      } else {
        Boolean pretty = Config.getAsBoolean("exporter.pretty_print", true);
        IParser parser = FhirR4.getContext().newJsonParser().setPrettyPrint(pretty);
        groupJson = parser.encodeResourceToString(group);
        outFilePath = f.toPath().resolve("groupInformation" + stop + ".json");
      }

      try {
        Files.write(outFilePath, Collections.singleton(groupJson), StandardOpenOption.CREATE_NEW);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
}