/**
   * Grabs the appropriate stuff from a request and returns a list of case_ids
   *
   * @param request
   * @return
   * @throws ProtocolException
   * @throws DaoException
   */
  public static ArrayList<String> getSampleIds(HttpServletRequest request)
      throws ProtocolException, DaoException {
    String samples = request.getParameter(WebService.CASE_LIST);
    String sampleSetId = request.getParameter(WebService.CASE_SET_ID);
    String sampleIdsKey = request.getParameter(WebService.CASE_IDS_KEY);

    if (sampleIdsKey != null) {
      samples = SampleSetUtil.getSampleIds(sampleIdsKey);
    }

    ArrayList<String> sampleList = new ArrayList<String>();
    if (sampleSetId != null && !(sampleSetId.equals("-1"))) {
      DaoSampleList dao = new DaoSampleList();
      SampleList selectedSampleList = dao.getSampleListByStableId(sampleSetId);
      if (selectedSampleList == null) {
        throw new ProtocolException(
            "Invalid " + WebService.CASE_SET_ID + ":  " + sampleSetId + ".");
      }
      sampleList = selectedSampleList.getSampleList();
    } else if (samples != null) {
      for (String _sample : samples.split("[\\s,]+")) {
        _sample = _sample.trim();
        if (_sample.length() == 0) continue;
        sampleList.add(_sample);
      }
    } else if (samples != null) { // todo: this is a hack, samples is just another word for patients
      return new ArrayList(Arrays.asList(samples.split(" ")));
    } else {
      throw new ProtocolException(
          WebService.CASE_SET_ID + " or " + WebService.CASE_LIST + " must be specified.");
    }
    return sampleList;
  }
  /**
   * Given an HttpServletRequest, determine all cancer_study_ids associated with it. cancer study
   * identifiers can be inferred from profile_ids, case_list_ids, or case_ids. this returns the set
   * of ALL POSSIBLE cancer study identifiers
   *
   * @param request
   * @return the cancer_study_ids associated with the request, which will be empty if none can be
   *     determined; or empty set if a problem arises.
   * @throws DaoException
   * @throws ProtocolException
   */
  public static HashSet<String> getCancerStudyIDs(HttpServletRequest request)
      throws DaoException, ProtocolException {

    HashSet<String> cancerStudies = new HashSet<String>();

    // a CANCER_STUDY_ID is explicitly provided, as in getGeneticProfiles, getCaseLists, etc.
    // make sure the cancer_study_id provided in the request points to a real study
    String studyIDstring = getCancerStudyId(request);
    if (studyIDstring != null) {
      if (DaoCancerStudy.doesCancerStudyExistByStableId(studyIDstring)) {
        cancerStudies.add(studyIDstring);
      }

      return cancerStudies;
    }

    // a genetic_profile_id is explicitly provided, as in getProfileData
    if (null != request.getParameter(WebService.GENETIC_PROFILE_ID)) {
      ArrayList<String> geneticProfileIds = getGeneticProfileId(request);
      for (String geneticProfileId : geneticProfileIds) {

        // that's the point of this code??
        //                if (geneticProfileId == null) {
        //                    return cancerStudies;
        //                }

        GeneticProfile aGeneticProfile =
            DaoGeneticProfile.getGeneticProfileByStableId(geneticProfileId);
        if (aGeneticProfile != null
            && DaoCancerStudy.doesCancerStudyExistByInternalId(
                aGeneticProfile.getCancerStudyId())) {
          cancerStudies.add(
              DaoCancerStudy.getCancerStudyByInternalId(aGeneticProfile.getCancerStudyId())
                  .getCancerStudyStableId());
        }
      }

      return cancerStudies;
    }

    // a patient_set_id is explicitly provided, as in getProfileData, getMutationData,
    // getClinicalData, etc.
    String sampleSetId = request.getParameter(WebService.CASE_SET_ID);
    if (sampleSetId != null) {
      DaoSampleList aDaoSampleList = new DaoSampleList();
      SampleList aSampleList = aDaoSampleList.getSampleListByStableId(sampleSetId);

      if (aSampleList != null
          && DaoCancerStudy.doesCancerStudyExistByInternalId(aSampleList.getCancerStudyId())) {
        cancerStudies.add(
            DaoCancerStudy.getCancerStudyByInternalId(aSampleList.getCancerStudyId())
                .getCancerStudyStableId());
      }

      return cancerStudies;
    }

    return cancerStudies;
  }
  /** Gets all Genomic Data. */
  private ProfileDataSummary getGenomicData(
      String cancerStudyId,
      HashMap<String, GeneticProfile> defaultGeneticProfileSet,
      SampleList defaultSampleSet,
      String geneListStr,
      ArrayList<SampleList> sampleList,
      HttpServletRequest request,
      HttpServletResponse response)
      throws IOException, ServletException, DaoException {

    // parse geneList, written in the OncoPrintSpec language (except for changes by XSS clean)
    double zScore =
        ZScoreUtil.getZScore(
            new HashSet<String>(defaultGeneticProfileSet.keySet()),
            new ArrayList<GeneticProfile>(defaultGeneticProfileSet.values()),
            request);
    double rppaScore = ZScoreUtil.getRPPAScore(request);

    ParserOutput theOncoPrintSpecParserOutput =
        OncoPrintSpecificationDriver.callOncoPrintSpecParserDriver(
            geneListStr,
            new HashSet<String>(defaultGeneticProfileSet.keySet()),
            new ArrayList<GeneticProfile>(defaultGeneticProfileSet.values()),
            zScore,
            rppaScore);

    ArrayList<String> geneList = new ArrayList<String>();
    geneList.addAll(theOncoPrintSpecParserOutput.getTheOncoPrintSpecification().listOfGenes());

    ArrayList<ProfileData> profileDataList = new ArrayList<ProfileData>();
    Set<String> warningUnion = new HashSet<String>();

    for (GeneticProfile profile : defaultGeneticProfileSet.values()) {
      try {
        GetProfileData remoteCall =
            new GetProfileData(
                profile, geneList, StringUtils.join(defaultSampleSet.getSampleList(), " "));
        ProfileData pData = remoteCall.getProfileData();
        warningUnion.addAll(remoteCall.getWarnings());
        profileDataList.add(pData);
      } catch (IllegalArgumentException e) {
        e.getStackTrace();
      }
    }

    ProfileMerger merger = new ProfileMerger(profileDataList);
    ProfileData mergedProfile = merger.getMergedProfile();

    ProfileDataSummary dataSummary =
        new ProfileDataSummary(
            mergedProfile,
            theOncoPrintSpecParserOutput.getTheOncoPrintSpecification(),
            zScore,
            rppaScore);
    return dataSummary;
  }
  /**
   * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
   *
   * @param request servlet request
   * @param response servlet response
   * @throws javax.servlet.ServletException if a servlet-specific error occurs
   * @throws java.io.IOException if an I/O error occurs
   */
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws IOException, ServletException {
    XDebug xdebug = new XDebug();
    xdebug.startTimer();

    response.setContentType("application/json");
    PrintWriter writer = response.getWriter();

    try {
      List resultsList = new LinkedList();

      // Get the gene list
      String geneList = request.getParameter(QueryBuilder.GENE_LIST);
      if (request instanceof XssRequestWrapper) {
        geneList = ((XssRequestWrapper) request).getRawParameter(QueryBuilder.GENE_LIST);
      }
      String cancerStudyIdListString = request.getParameter(QueryBuilder.CANCER_STUDY_LIST);
      String[] cancerStudyIdList = cancerStudyIdListString.split(",");

      // Get the priority
      Integer dataTypePriority;
      try {
        dataTypePriority =
            Integer.parseInt(request.getParameter(QueryBuilder.DATA_PRIORITY).trim());
      } catch (NumberFormatException e) {
        dataTypePriority = 0;
      }

      //  Cancer All Cancer Studies
      List<CancerStudy> cancerStudiesList = accessControl.getCancerStudies();
      HashMap<String, Boolean> studyMap = new HashMap<>();
      for (String studyId : cancerStudyIdList) {
        studyMap.put(studyId, Boolean.TRUE);
      }
      for (CancerStudy cancerStudy : cancerStudiesList) {
        String cancerStudyId = cancerStudy.getCancerStudyStableId();
        if (!studyMap.containsKey(cancerStudyId)) {
          continue;
        }
        if (cancerStudyId.equalsIgnoreCase("all")) continue;

        Map cancerMap = new LinkedHashMap();
        cancerMap.put("studyId", cancerStudyId);
        cancerMap.put("typeOfCancer", cancerStudy.getTypeOfCancerId());

        //  Get all Genetic Profiles Associated with this Cancer Study ID.
        ArrayList<GeneticProfile> geneticProfileList =
            GetGeneticProfiles.getGeneticProfiles(cancerStudyId);

        //  Get all Patient Lists Associated with this Cancer Study ID.
        ArrayList<SampleList> sampleSetList = GetSampleLists.getSampleLists(cancerStudyId);

        //  Get the default patient set
        AnnotatedSampleSets annotatedSampleSets =
            new AnnotatedSampleSets(sampleSetList, dataTypePriority);
        SampleList defaultSampleSet = annotatedSampleSets.getDefaultSampleList();
        if (defaultSampleSet == null) {
          continue;
        }

        List<String> sampleIds = defaultSampleSet.getSampleList();

        //  Get the default genomic profiles
        CategorizedGeneticProfileSet categorizedGeneticProfileSet =
            new CategorizedGeneticProfileSet(geneticProfileList);
        HashMap<String, GeneticProfile> defaultGeneticProfileSet = null;
        switch (dataTypePriority) {
          case 2:
            defaultGeneticProfileSet = categorizedGeneticProfileSet.getDefaultCopyNumberMap();
            break;
          case 1:
            defaultGeneticProfileSet = categorizedGeneticProfileSet.getDefaultMutationMap();
            break;
          case 0:
          default:
            defaultGeneticProfileSet =
                categorizedGeneticProfileSet.getDefaultMutationAndCopyNumberMap();
        }

        String mutationProfile = "", cnaProfile = "";
        for (GeneticProfile geneticProfile : defaultGeneticProfileSet.values()) {
          GeneticAlterationType geneticAlterationType = geneticProfile.getGeneticAlterationType();
          if (geneticAlterationType.equals(GeneticAlterationType.COPY_NUMBER_ALTERATION)) {
            cnaProfile = geneticProfile.getStableId();
          } else if (geneticAlterationType.equals(GeneticAlterationType.MUTATION_EXTENDED)) {
            mutationProfile = geneticProfile.getStableId();
          }
        }

        cancerMap.put("mutationProfile", mutationProfile);
        cancerMap.put("cnaProfile", cnaProfile);

        cancerMap.put("caseSetId", defaultSampleSet.getStableId());
        cancerMap.put("caseSetLength", sampleIds.size());

        ProfileDataSummary genomicData =
            getGenomicData(
                cancerStudyId,
                defaultGeneticProfileSet,
                defaultSampleSet,
                geneList,
                sampleSetList,
                request,
                response);

        ArrayList<GeneWithScore> geneFrequencyList = genomicData.getGeneFrequencyList();
        ArrayList<String> genes = new ArrayList<String>();
        for (GeneWithScore geneWithScore : geneFrequencyList) genes.add(geneWithScore.getGene());
        int noOfMutated = 0,
            noOfCnaUp = 0,
            noOfCnaDown = 0,
            noOfCnaLoss = 0,
            noOfCnaGain = 0,
            noOfOther = 0,
            noOfAll = 0;

        boolean skipStudy = defaultGeneticProfileSet.isEmpty();
        if (!skipStudy) {

          for (String sampleId : sampleIds) {
            if (sampleId == null) {
              continue;
            }
            if (!genomicData.isCaseAltered(sampleId)) continue;

            boolean isAnyMutated = false,
                isAnyCnaUp = false,
                isAnyCnaDown = false,
                isAnyCnaLoss = false,
                isAnyCnaGain = false;

            for (String gene : genes) {
              isAnyMutated |= genomicData.isGeneMutated(gene, sampleId);
              GeneticTypeLevel cnaLevel = genomicData.getCNALevel(gene, sampleId);
              boolean isCnaUp = cnaLevel != null && cnaLevel.equals(GeneticTypeLevel.Amplified);
              isAnyCnaUp |= isCnaUp;
              boolean isCnaDown =
                  cnaLevel != null && cnaLevel.equals(GeneticTypeLevel.HomozygouslyDeleted);
              isAnyCnaDown |= isCnaDown;
              boolean isCnaLoss =
                  cnaLevel != null && cnaLevel.equals(GeneticTypeLevel.HemizygouslyDeleted);
              isAnyCnaLoss |= isCnaLoss;
              boolean isCnaGain = cnaLevel != null && cnaLevel.equals(GeneticTypeLevel.Gained);
              isAnyCnaGain |= isCnaGain;
            }

            boolean isAnyCnaChanged = isAnyCnaUp || isAnyCnaDown;
            if (isAnyMutated && !isAnyCnaChanged) noOfMutated++;
            else if (isAnyMutated && isAnyCnaChanged) noOfOther++;
            else if (isAnyCnaUp) noOfCnaUp++;
            else if (isAnyCnaDown) noOfCnaDown++;
            else if (isAnyCnaGain) noOfCnaGain++;
            else if (isAnyCnaLoss) noOfCnaLoss++;

            noOfAll++;
          }
        }

        Map alterations = new LinkedHashMap();
        cancerMap.put("alterations", alterations);
        alterations.put("all", noOfAll);
        alterations.put("mutation", noOfMutated);
        alterations.put("cnaUp", noOfCnaUp);
        alterations.put("cnaDown", noOfCnaDown);
        alterations.put("cnaLoss", noOfCnaLoss);
        alterations.put("cnaGain", noOfCnaGain);
        alterations.put("other", noOfOther);
        cancerMap.put("genes", genes);
        cancerMap.put("skipped", skipStudy);

        resultsList.add(cancerMap);
      }

      JSONValue.writeJSONString(resultsList, writer);
    } catch (DaoException e) {
      throw new ServletException(e);
    } catch (ProtocolException e) {
      throw new ServletException(e);
    } finally {
      writer.close();
    }
  }