/** Assigns the lead unit of the proposal to the given principal investigator */
  public void assignLeadUnit(ProposalPerson person, String unitNumber) {
    if (person.containsUnit(unitNumber)) {
      person.getUnit(unitNumber).setLeadUnit(true);
      return;
    }

    ProposalPersonUnit unit = createProposalPersonUnit(unitNumber, person);
    unit.setLeadUnit(true);
    addUnitToPerson(person, unit);
  }
  @Override
  public void addUnitToPerson(ProposalPerson person, ProposalPersonUnit unit) {
    if (unit == null) {
      throw new IllegalArgumentException("Cannot add null units to a ProposalPerson instance");
    }

    if (!person.containsUnit(unit.getUnitNumber())) {
      unit.setProposalPerson(person);

      person.addUnit(unit);
      unit.refreshReferenceObject("unit");
    }
  }
  /**
   * Uses a <code>{@link Unit}</code> obtained from the <code>{@link Unit}</code> lookup to create a
   * <code>{@link ProposalPersonUnit}</code> instance.
   *
   * @param unitId
   * @return ProposalPersonUnit
   */
  public ProposalPersonUnit createProposalPersonUnit(String unitId, ProposalPerson person) {
    ProposalPersonUnit retval = new ProposalPersonUnit();
    Map valueMap = new HashMap();
    valueMap.put("unitNumber", unitId);
    Collection<Unit> units = getBusinessObjectService().findMatching(Unit.class, valueMap);

    for (Unit found : units) {
      retval.setUnitNumber(found.getUnitNumber());
      retval.setUnit(found);
    }

    for (InvestigatorCreditType creditType : getInvestigatorCreditTypes()) {
      ProposalUnitCreditSplit creditSplit = new ProposalUnitCreditSplit();
      creditSplit.setProposalPersonUnit(retval);
      creditSplit.setInvCreditTypeCode(creditType.getCode());
      creditSplit.setCredit(new ScaleTwoDecimal(0));
      retval.getCreditSplits().add(creditSplit);
    }

    return retval;
  }
  public void addProposalPerson(
      ProposalPerson proposalPerson, ProposalDevelopmentDocument document) {
    getPersonEditableService().populateContactFields(proposalPerson);
    document.getDevelopmentProposal().addProposalPerson(proposalPerson);

    LOG.info(
        "Added Proposal Person with proposalNumber = "
            + document.getDevelopmentProposal().getProposalNumber()
            + " and proposalPersonNumber = "
            + proposalPerson.getProposalPersonNumber());
    // handle lead unit for investigators respective to coi or pi
    if (proposalPerson.isPrincipalInvestigator()) {
      assignLeadUnit(proposalPerson, document.getDevelopmentProposal().getOwnedByUnitNumber());
    } else {
      // Lead Unit information needs to be removed in case the person used to be a PI
      ProposalPersonUnit unit =
          proposalPerson.getUnit(document.getDevelopmentProposal().getOwnedByUnitNumber());
      if (unit != null) {
        unit.setLeadUnit(false);
      }
    }
    if (proposalPerson.getHomeUnit() != null) {
      proposalPerson.refreshReferenceObject("homeUnitRef");
      String divisionName =
          getProposalPersonService().getProposalPersonDivisionName(proposalPerson);
      proposalPerson.setDivision(divisionName);
    } else {
      proposalPerson.setDivision(ROLODEX_PERSON);
    }
    if (proposalPerson.getProposalPersonRoleId().equals(PRINCIPAL_INVESTIGATOR_ROLE)
        || proposalPerson.getProposalPersonRoleId().equals(CO_INVESTIGATOR_ROLE)) {
      if (isNotBlank(proposalPerson.getHomeUnit())
          && isValidHomeUnit(proposalPerson, proposalPerson.getHomeUnit())) {
        addUnitToPerson(
            proposalPerson, createProposalPersonUnit(proposalPerson.getHomeUnit(), proposalPerson));
      }
    }

    populateProposalPerson(proposalPerson, document);
  }
 /**
  * It populates the Active credit type in the proposalpersoncreditsplit and unitcreditsplit
  *
  * @param document
  * @return true or false
  */
 public void populateActiveCredittypesPerson(ProposalDevelopmentDocument document) {
   Collection<InvestigatorCreditType> invcrdttype = getInvestigatorCreditTypes();
   for (ProposalPerson person : document.getDevelopmentProposal().getInvestigators()) {
     for (InvestigatorCreditType invcredtype : invcrdttype) {
       boolean creditTypeFound = false;
       for (ProposalPersonCreditSplit proposalpersoncrdt : person.getCreditSplits()) {
         if ((invcredtype.getCode().equals(proposalpersoncrdt.getInvCreditTypeCode()))) {
           creditTypeFound = true;
           break;
         }
       }
       if (!creditTypeFound) {
         ProposalPersonCreditSplit creditSplit = new ProposalPersonCreditSplit();
         creditSplit.setProposalPerson(person);
         creditSplit.setInvCreditTypeCode(invcredtype.getCode());
         creditSplit.setCredit(new ScaleTwoDecimal(0));
         person.getCreditSplits().add(creditSplit);
       }
     }
     for (ProposalPersonUnit unitsplit : person.getUnits()) {
       for (InvestigatorCreditType invcrdtype : invcrdttype) {
         boolean creditTypeFound = false;
         for (ProposalUnitCreditSplit unitcreditsplit : unitsplit.getCreditSplits()) {
           if ((invcrdtype.getCode().equals(unitcreditsplit.getInvCreditTypeCode()))) {
             creditTypeFound = true;
             break;
           }
         }
         if (!creditTypeFound) {
           ProposalUnitCreditSplit creditSplit = new ProposalUnitCreditSplit();
           creditSplit.setProposalPersonUnit(unitsplit);
           creditSplit.setInvCreditTypeCode(invcrdtype.getCode());
           creditSplit.setCredit(new ScaleTwoDecimal(0));
           unitsplit.getCreditSplits().add(creditSplit);
         }
       }
     }
   }
 }
  @Override
  public List<ProposalCreditSplitListDto> createCreditSplitListItems(
      List<ProposalPerson> investigators) {
    List<ProposalCreditSplitListDto> creditSplitListItems =
        new ArrayList<ProposalCreditSplitListDto>();
    Map<String, ProposalPersonCreditSplit> totalInvestigatorSplits =
        new HashMap<String, ProposalPersonCreditSplit>();
    for (ProposalPerson investigator : investigators) {
      ProposalCreditSplitListDto investigatorLine = new ProposalCreditSplitListDto();
      investigatorLine.setDescription(investigator.getFullName());
      investigatorLine.setLineType("investigator");
      investigatorLine.getCreditSplits().addAll(investigator.getCreditSplits());
      creditSplitListItems.add(investigatorLine);
      for (ProposalPersonCreditSplit invesitgatorCreditSplit : investigator.getCreditSplits()) {
        if (totalInvestigatorSplits.containsKey(invesitgatorCreditSplit.getInvCreditTypeCode())) {
          ProposalPersonCreditSplit creditSplit =
              totalInvestigatorSplits.get(invesitgatorCreditSplit.getInvCreditTypeCode());
          creditSplit.setCredit(creditSplit.getCredit().add(invesitgatorCreditSplit.getCredit()));
        } else {
          ProposalPersonCreditSplit creditSplit = new ProposalPersonCreditSplit();
          creditSplit.setCredit(invesitgatorCreditSplit.getCredit());
          totalInvestigatorSplits.put(invesitgatorCreditSplit.getInvCreditTypeCode(), creditSplit);
        }
      }

      Map<String, ProposalUnitCreditSplit> totalUnitSplits =
          new HashMap<String, ProposalUnitCreditSplit>();
      for (ProposalPersonUnit unit : investigator.getUnits()) {
        ProposalCreditSplitListDto unitLine = new ProposalCreditSplitListDto();
        unitLine.setDescription(unit.getUnitNumber() + " - " + unit.getUnit().getUnitName());
        unitLine.getCreditSplits().addAll(unit.getCreditSplits());
        unitLine.setLineType("unit");
        creditSplitListItems.add(unitLine);
        for (ProposalUnitCreditSplit unitCreditSplit : unit.getCreditSplits()) {
          if (totalUnitSplits.containsKey(unitCreditSplit.getInvCreditTypeCode())) {
            ProposalUnitCreditSplit creditSplit =
                totalUnitSplits.get(unitCreditSplit.getInvCreditTypeCode());
            creditSplit.setCredit(creditSplit.getCredit().add(unitCreditSplit.getCredit()));
          } else {
            ProposalUnitCreditSplit creditSplit = new ProposalUnitCreditSplit();
            creditSplit.setCredit(unitCreditSplit.getCredit());
            totalUnitSplits.put(unitCreditSplit.getInvCreditTypeCode(), creditSplit);
          }
        }
      }

      ProposalCreditSplitListDto unitTotalLine = new ProposalCreditSplitListDto();
      unitTotalLine.setDescription("Unit Total:");
      unitTotalLine.setLineType("unit-total");
      for (Map.Entry<String, ProposalUnitCreditSplit> entry : totalUnitSplits.entrySet()) {
        unitTotalLine.getCreditSplits().add(0, entry.getValue());
      }
      creditSplitListItems.add(unitTotalLine);
    }

    ProposalCreditSplitListDto investigatorTotalLine = new ProposalCreditSplitListDto();
    investigatorTotalLine.setDescription("Investigator Total:");
    investigatorTotalLine.setLineType("investigator-total");
    for (Map.Entry<String, ProposalPersonCreditSplit> entry : totalInvestigatorSplits.entrySet()) {
      investigatorTotalLine.getCreditSplits().add(0, entry.getValue());
    }
    creditSplitListItems.add(investigatorTotalLine);

    return creditSplitListItems;
  }
  /**
   * Everytime something changes that will effect credit split values, this gets called to generate
   * a graph of the new data.
   *
   * @param document
   * @return Map
   */
  public Map calculateCreditSplitTotals(ProposalDevelopmentDocument document) {
    Map<String, Map<String, ScaleTwoDecimal>> retval =
        new HashMap<String, Map<String, ScaleTwoDecimal>>();

    // Initialize investigator credit types if there aren't any
    if (document.getDevelopmentProposal().getInvestigatorCreditTypes() == null
        || document.getDevelopmentProposal().getInvestigatorCreditTypes().size() == 0) {
      document.getDevelopmentProposal().setInvestigatorCreditTypes(getInvestigatorCreditTypes());
    }

    Collection<InvestigatorCreditType> creditTypes =
        document.getDevelopmentProposal().getInvestigatorCreditTypes();

    for (ProposalPerson investigator : document.getDevelopmentProposal().getInvestigators()) {
      Map<String, ScaleTwoDecimal> creditTypeTotals =
          retval.get(investigator.getProposalPersonNumber().toString());
      Map<String, ScaleTwoDecimal> investigatorCreditTypeTotals =
          retval.get(PROPOSAL_PERSON_INVESTIGATOR);

      if (creditTypeTotals == null) {
        creditTypeTotals = new HashMap<String, ScaleTwoDecimal>();
        retval.put(investigator.getProposalPersonNumber().toString(), creditTypeTotals);
      }
      if (investigatorCreditTypeTotals == null) {
        investigatorCreditTypeTotals = new HashMap<String, ScaleTwoDecimal>();
        retval.put(PROPOSAL_PERSON_INVESTIGATOR, investigatorCreditTypeTotals);
      }

      // Initialize everything to zero
      for (InvestigatorCreditType creditType : creditTypes) {
        ScaleTwoDecimal totalCredit = creditTypeTotals.get(creditType.getCode());

        if (totalCredit == null) {
          totalCredit = new ScaleTwoDecimal(0);
          creditTypeTotals.put(creditType.getCode(), totalCredit);
        }
        ScaleTwoDecimal investigatorTotalCredit =
            investigatorCreditTypeTotals.get(creditType.getCode());

        if (investigatorTotalCredit == null) {
          investigatorTotalCredit = new ScaleTwoDecimal(0);
          investigatorCreditTypeTotals.put(creditType.getCode(), investigatorTotalCredit);
        }
        // set investigator credit total
        for (CreditSplit creditSplit : investigator.getCreditSplits()) {
          if (creditSplit.getInvCreditTypeCode().equals(creditType.getCode())) {
            investigatorCreditTypeTotals.put(
                creditType.getCode(), investigatorTotalCredit.add(creditSplit.getCredit()));
          }
        }
      }

      for (ProposalPersonUnit unit : investigator.getUnits()) {
        for (CreditSplit creditSplit : unit.getCreditSplits()) {
          ScaleTwoDecimal totalCredit = creditTypeTotals.get(creditSplit.getInvCreditTypeCode());

          if (totalCredit == null) {
            totalCredit = new ScaleTwoDecimal(0);
            creditTypeTotals.put(creditSplit.getInvCreditTypeCode(), totalCredit);
          }
          creditTypeTotals.put(
              creditSplit.getInvCreditTypeCode(), totalCredit.add(creditSplit.getCredit()));
        }
      }
    }

    return retval;
  }