/**
   * Publish a given Bundle file
   *
   * @param request HttpRequest
   * @param response HttpResponse
   * @throws FileUploadException If fails uploading the file
   * @throws IOException If fails reading the given File content or sending back to the user a
   *     response
   */
  public void uploadBundle(HttpServletRequest request, HttpServletResponse response)
      throws FileUploadException, IOException {

    try {
      if (!APILocator.getLayoutAPI()
          .doesUserHaveAccessToPortlet("EXT_CONTENT_PUBLISHING_TOOL", getUser())) {
        response.sendError(401);
        return;
      }
    } catch (DotDataException e1) {
      Logger.error(RemotePublishAjaxAction.class, e1.getMessage(), e1);
      response.sendError(401);
      return;
    }

    FileItemFactory factory = new DiskFileItemFactory();
    ServletFileUpload upload = new ServletFileUpload(factory);
    @SuppressWarnings("unchecked")
    List<FileItem> items = (List<FileItem>) upload.parseRequest(request);

    InputStream bundle = items.get(0).getInputStream();
    String bundleName = items.get(0).getName();
    String bundlePath = ConfigUtils.getBundlePath() + File.separator;
    String bundleFolder = bundleName.substring(0, bundleName.indexOf(".tar.gz"));
    String endpointId = getUser().getUserId();
    response.setContentType("text/html; charset=utf-8");
    PrintWriter out = response.getWriter();

    PublishAuditStatus status;
    try {
      status = PublishAuditAPI.getInstance().updateAuditTable(endpointId, null, bundleFolder);

      // Write file on FS
      FileUtil.writeToFile(bundle, bundlePath + bundleName);

      if (!status.getStatus().equals(Status.PUBLISHING_BUNDLE)) {
        new Thread(new PublishThread(bundleName, null, endpointId, status)).start();
      }

      out.print(
          "<html><head><script>isLoaded = true;</script></head><body><textarea>{'status':'success'}</textarea></body></html>");

    } catch (DotPublisherException e) {
      // TODO Auto-generated catch block
      out.print(
          "<html><head><script>isLoaded = true;</script></head><body><textarea>{'status':'error'}</textarea></body></html>");
    }
  }
  /**
   * Allow the user to send or try to send again failed and successfully sent bundles, in order to
   * do that<br>
   * we send the bundle again to que publisher queue job which will try to remote publish again the
   * bundle.
   *
   * @param request HttpRequest
   * @param response HttpResponse
   * @throws IOException If fails sending back to the user a proper response
   * @throws DotPublisherException If fails retrieving the Bundle related information like elements
   *     on it and statuses
   * @throws LanguageException If fails using i18 messages
   */
  public void retry(HttpServletRequest request, HttpServletResponse response)
      throws IOException, DotPublisherException, LanguageException {

    PublisherAPI publisherAPI = PublisherAPI.getInstance();
    PublishAuditAPI publishAuditAPI = PublishAuditAPI.getInstance();

    // Read the parameters
    String bundlesIds = request.getParameter("bundlesIds");
    String[] ids = bundlesIds.split(",");

    StringBuilder responseMessage = new StringBuilder();

    for (String bundleId : ids) {

      if (bundleId.trim().isEmpty()) {
        continue;
      }

      PublisherConfig basicConfig = new PublisherConfig();
      basicConfig.setId(bundleId);
      File bundleRoot = BundlerUtil.getBundleRoot(basicConfig);

      // Get the audit records related to this bundle
      PublishAuditStatus status = PublishAuditAPI.getInstance().getPublishAuditStatus(bundleId);
      String pojo_string = status.getStatusPojo().getSerialized();
      PublishAuditHistory auditHistory = PublishAuditHistory.getObjectFromString(pojo_string);

      // First we need to verify is this bundle is already in the queue job
      List<PublishQueueElement> foundBundles = publisherAPI.getQueueElementsByBundleId(bundleId);
      if (foundBundles != null && !foundBundles.isEmpty()) {
        appendMessage(responseMessage, "publisher_retry.error.already.in.queue", bundleId, true);
        continue;
      }

      // We will be able to retry failed and successfully bundles
      if (!(status.getStatus().equals(Status.FAILED_TO_PUBLISH)
          || status.getStatus().equals(Status.SUCCESS))) {
        appendMessage(responseMessage, "publisher_retry.error.only.failed.publish", bundleId, true);
        continue;
      }

      /*
      Verify if the bundle exist and was created correctly..., meaning, if there is not a .tar.gz file is because
      something happened on the creation of the bundle.
       */
      File bundleFile =
          new File(
              bundleRoot
                  + File.separator
                  + ".."
                  + File.separator
                  + basicConfig.getId()
                  + ".tar.gz");
      if (!bundleFile.exists()) {
        Logger.error(this.getClass(), "No Bundle with id: " + bundleId + " found.");
        appendMessage(responseMessage, "publisher_retry.error.not.found", bundleId, true);
        continue;
      }

      if (!BundlerUtil.bundleExists(basicConfig)) {
        Logger.error(
            this.getClass(), "No Bundle Descriptor for bundle id: " + bundleId + " found.");
        appendMessage(
            responseMessage, "publisher_retry.error.not.descriptor.found", bundleId, true);
        continue;
      }

      try {

        // Read the bundle to see what kind of configuration we need to apply
        String bundlePath = ConfigUtils.getBundlePath() + File.separator + basicConfig.getId();
        File xml = new File(bundlePath + File.separator + "bundle.xml");
        PushPublisherConfig config = (PushPublisherConfig) BundlerUtil.xmlToObject(xml);

        // We can not retry Received Bundles, just bundles that we are trying to send
        Boolean sending = sendingBundle(request, config, bundleId);
        if (!sending) {
          appendMessage(
              responseMessage, "publisher_retry.error.cannot.retry.received", bundleId, true);
          continue;
        }

        if (status.getStatus().equals(Status.SUCCESS)) {

          // Get the bundle
          Bundle bundle = APILocator.getBundleAPI().getBundleById(bundleId);
          if (bundle == null) {
            Logger.error(this.getClass(), "No Bundle with id: " + bundleId + " found.");
            appendMessage(responseMessage, "publisher_retry.error.not.found", bundleId, true);
            continue;
          }
          bundle.setForcePush(true);
          APILocator.getBundleAPI().updateBundle(bundle);
        }

        // Clean the number of tries, we want to try it again
        auditHistory.setNumTries(0);
        publishAuditAPI.updatePublishAuditStatus(
            config.getId(), status.getStatus(), auditHistory, true);

        // Get the identifiers on this bundle
        HashSet<String> identifiers = new HashSet<String>();
        List<PublishQueueElement> assets = config.getAssets();
        if (config.getLuceneQueries() != null && !config.getLuceneQueries().isEmpty()) {
          identifiers.addAll(PublisherUtil.getContentIds(config.getLuceneQueries()));
        }
        if (assets != null && !assets.isEmpty()) {
          for (PublishQueueElement asset : assets) {
            identifiers.add(asset.getAsset());
          }
        }

        // Now depending of the operation lets add it to the queue job
        if (config.getOperation().equals(PushPublisherConfig.Operation.PUBLISH)) {
          publisherAPI.addContentsToPublish(
              new ArrayList<String>(identifiers), bundleId, new Date(), getUser());
        } else {
          publisherAPI.addContentsToUnpublish(
              new ArrayList<String>(identifiers), bundleId, new Date(), getUser());
        }

        // Success...
        appendMessage(responseMessage, "publisher_retry.success", bundleId, false);
      } catch (Exception e) {
        Logger.error(
            this.getClass(),
            "Error trying to add bundle id: " + bundleId + " to the Publishing Queue.",
            e);
        appendMessage(responseMessage, "publisher_retry.error.adding.to.queue", bundleId, true);
      }
    }

    response.getWriter().println(responseMessage.toString());
  }