// TODO Need to refactor this method to get Message statistic by default.
  // This is to be consistance with UI which uses message stats, and for
  // calculating remaining hours.
  @Override
  public ContainerTranslationStatistics getStatistics(
      String projectSlug,
      String iterationSlug,
      boolean includeDetails,
      boolean includeWordStats,
      String[] locales) {
    LocaleId[] localeIds;

    // if no locales are specified, search in all locales
    if (locales.length == 0) {
      List<HLocale> iterationLocales =
          localeServiceImpl.getSupportedLangugeByProjectIteration(projectSlug, iterationSlug);
      localeIds = new LocaleId[iterationLocales.size()];
      for (int i = 0, iterationLocalesSize = iterationLocales.size();
          i < iterationLocalesSize;
          i++) {
        HLocale loc = iterationLocales.get(i);
        localeIds[i] = loc.getLocaleId();
      }
    } else {
      localeIds = new LocaleId[locales.length];
      for (int i = 0; i < locales.length; i++) {
        localeIds[i] = new LocaleId(locales[i]);
      }
    }

    HProjectIteration iteration = projectIterationDAO.getBySlug(projectSlug, iterationSlug);

    if (iteration == null) {
      throw new NoSuchEntityException(projectSlug + "/" + iterationSlug);
    }

    Map<String, TransUnitCount> transUnitIterationStats =
        projectIterationDAO.getAllStatisticsForContainer(iteration.getId());
    Map<String, TransUnitWords> wordIterationStats =
        projectIterationDAO.getAllWordStatsStatistics(iteration.getId());

    ContainerTranslationStatistics iterationStats = new ContainerTranslationStatistics();
    iterationStats.setId(iterationSlug);
    iterationStats.addRef(
        new Link(
            URI.create(zPathService.generatePathForProjectIteration(iteration)),
            "statSource",
            "PROJ_ITER"));
    long iterationTotalMssgs =
        projectIterationDAO.getTotalMessageCountForIteration(iteration.getId());
    long iterationTotalWords = projectIterationDAO.getTotalWordCountForIteration(iteration.getId());

    for (LocaleId locId : localeIds) {
      // trans unit level stats
      TransUnitCount count = transUnitIterationStats.get(locId.getId());
      // Stats might not return anything if nothing is translated
      if (count == null) {
        count = new TransUnitCount(0, 0, (int) iterationTotalMssgs);
      }

      HTextFlowTarget target =
          localeServiceImpl.getLastTranslated(projectSlug, iterationSlug, locId);

      String lastModifiedBy = "";
      Date lastModifiedDate = null;

      if (target != null) {
        lastModifiedDate = target.getLastChanged();
        if (target.getLastModifiedBy() != null) {
          lastModifiedBy = target.getLastModifiedBy().getAccount().getUsername();
        }
      }

      TransUnitWords wordCount = wordIterationStats.get(locId.getId());
      if (wordCount == null) {
        wordCount = new TransUnitWords(0, 0, (int) iterationTotalWords);
      }

      TranslationStatistics transUnitStats =
          getMessageStats(count, locId, lastModifiedDate, lastModifiedBy);
      transUnitStats.setRemainingHours(StatisticsUtil.getRemainingHours(wordCount));
      iterationStats.addStats(transUnitStats);

      // word level stats
      if (includeWordStats) {
        TranslationStatistics wordsStats =
            getWordsStats(wordCount, locId, lastModifiedDate, lastModifiedBy);
        wordsStats.setRemainingHours(StatisticsUtil.getRemainingHours(wordCount));
        iterationStats.addStats(wordsStats);
      }
    }

    // TODO Do in a single query
    if (includeDetails) {
      for (String docId : iteration.getDocuments().keySet()) {
        iterationStats.addDetailedStats(
            this.getStatistics(projectSlug, iterationSlug, docId, includeWordStats, locales));
      }
    }

    return iterationStats;
  }
  @Override
  public ContainerTranslationStatistics getStatistics(
      String projectSlug,
      String iterationSlug,
      String docId,
      boolean includeWordStats,
      String[] locales) {
    LocaleId[] localeIds;

    // if no locales are specified, search in all locales
    if (locales.length == 0) {
      List<HLocale> iterationLocales =
          localeServiceImpl.getSupportedLangugeByProjectIteration(projectSlug, iterationSlug);
      localeIds = new LocaleId[iterationLocales.size()];
      for (int i = 0, iterationLocalesSize = iterationLocales.size();
          i < iterationLocalesSize;
          i++) {
        HLocale loc = iterationLocales.get(i);
        localeIds[i] = loc.getLocaleId();
      }
    } else {
      localeIds = new LocaleId[locales.length];
      for (int i = 0; i < locales.length; i++) {
        localeIds[i] = new LocaleId(locales[i]);
      }
    }

    HDocument document =
        documentDAO.getByProjectIterationAndDocId(projectSlug, iterationSlug, docId);

    if (document == null) {
      throw new NoSuchEntityException(projectSlug + "/" + iterationSlug + "/" + docId);
    }

    ContainerTranslationStatistics docStatistics = new ContainerTranslationStatistics();
    docStatistics.setId(docId);
    docStatistics.addRef(
        new Link(URI.create(zPathService.generatePathForDocument(document)), "statSource", "DOC"));

    for (LocaleId localeId : localeIds) {
      ContainerTranslationStatistics docStats = getDocStatistics(document.getId(), localeId);

      DocumentStatus docStatus =
          translationStateCacheImpl.getDocumentStatus(document.getId(), localeId);

      TranslationStatistics docWordStatistic = docStats.getStats(localeId.getId(), StatUnit.WORD);
      TranslationStatistics docMsgStatistic = docStats.getStats(localeId.getId(), StatUnit.MESSAGE);

      docMsgStatistic.setLastTranslatedBy(docStatus.getLastTranslatedBy());
      docMsgStatistic.setLastTranslatedDate(docStatus.getLastTranslatedDate());
      docMsgStatistic.setLastTranslated(
          getLastTranslated(docStatus.getLastTranslatedDate(), docStatus.getLastTranslatedBy()));
      docStatistics.addStats(docMsgStatistic);

      if (includeWordStats) {
        docWordStatistic.setLastTranslatedBy(docStatus.getLastTranslatedBy());
        docWordStatistic.setLastTranslatedDate(docStatus.getLastTranslatedDate());
        docWordStatistic.setLastTranslated(
            getLastTranslated(docStatus.getLastTranslatedDate(), docStatus.getLastTranslatedBy()));
        docStatistics.addStats(docWordStatistic);
      }
    }
    return docStatistics;
  }