class InstallPackagesCheck extends AbstractCheckDescriptor {

  @Override
  public void perform(PrerequisiteCheck prerequisiteCheck, PrereqCheckRequest request) throws AmbariException {
    final String clusterName = request.getClusterName();
    final Cluster cluster = clustersProvider.get().getCluster(clusterName);
    RepositoryVersionEntity repositoryVersion = request.getTargetRepositoryVersion();

    final StackId targetStackId = repositoryVersion.getStackId();

    if (!repositoryVersion.getVersion().matches("^\\d+(\\.\\d+)*\\-\\d+$")) {
      String message = MessageFormat.format("The Repository Version {0} for Stack {1} must contain a \"-\" followed by a build number. " +
              "Make sure that another registered repository does not have the same repo URL or " +
              "shares the same build number. Next, try reinstalling the Repository Version.", repositoryVersion.getVersion(), repositoryVersion.getStackVersion());
      prerequisiteCheck.getFailedOn().add("Repository Version " + repositoryVersion.getVersion());
      prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL);
      prerequisiteCheck.setFailReason(message);
      return;
    }

    final Set<HostDetail> failedHosts = new TreeSet<>();

    for (Host host : cluster.getHosts()) {
      if (host.getMaintenanceState(cluster.getClusterId()) != MaintenanceState.ON) {
        for (HostVersionEntity hve : hostVersionDaoProvider.get().findByHost(host.getHostName())) {
          if (StringUtils.equals(hve.getRepositoryVersion().getVersion(), repositoryVersion.getVersion())
              && hve.getState() == RepositoryVersionState.INSTALL_FAILED) {

            failedHosts.add(new HostDetail(host.getHostId(), host.getHostName()));
          }
        }
      }
    }

    if (!failedHosts.isEmpty()) {
      String message = MessageFormat.format("Hosts in cluster [{0},{1},{2},{3}] are in INSTALL_FAILED state because " +
              "Install Packages had failed. Please re-run Install Packages, if necessary place following hosts " +
              "in Maintenance mode: {4}", cluster.getClusterName(), targetStackId.getStackName(),
          targetStackId.getStackVersion(), repositoryVersion.getVersion(),
          StringUtils.join(failedHosts, ", "));

      LinkedHashSet<String> failedHostNames = failedHosts.stream().map(
          failedHost -> failedHost.hostName).collect(
              Collectors.toCollection(LinkedHashSet::new));

      prerequisiteCheck.setFailedOn(failedHostNames);
      prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL);
      prerequisiteCheck.setFailReason(message);
      prerequisiteCheck.getFailedDetail().addAll(failedHosts);

      return;
    }

    prerequisiteCheck.setStatus(PrereqCheckStatus.PASS);
  }

  public  InstallPackagesCheck();

}