/** Changes the expire date and alert for the new specified */
  @RequestMapping(value = "/changeExpire", method = RequestMethod.GET)
  public ResponseEntity<?> changeExpireDate(
      HttpServletRequest request,
      @RequestParam(value = "url", required = false) String hash,
      @RequestParam(value = "expire", required = false) String expire,
      @RequestParam(value = "days", required = false) String days) {
    hash = hash.substring(1, hash.length() - 1);

    /* Changes expire date */
    ShortURL su = shortURLRepository.findByHash(hash);
    logger.info("su: " + su);
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    Date newExpire = null;
    try {
      newExpire = sdf.parse(expire);
    } catch (ParseException e) {
      e.printStackTrace();
      logger.info("Error with introduced alert date");
    }
    su.setExpire(newExpire);
    logger.info("Updating ShortURL: " + su);
    shortURLRepository.save(su);

    /* Changes alert date */
    Alert a = alertRepository.findByHash(hash);
    Date alertDate = processAlertDate(expire, days);
    if (a != null) {
      /* If alert already exists, updates its alert date */
      a.setDate(alertDate);
      logger.info("Updating alert: " + a);
      alertRepository.save(a);
    } else {
      /* If alert does not exist, creates a new one */
      String mail = UrlShortenerControllerWithLogs.getOwnerMail();
      logger.info("Setting new alert");
      alertRepository.save(new Alert(mail, hash, alertDate));
    }
    return new ResponseEntity<>(HttpStatus.OK);
  }
  @RequestMapping(value = "/rec/rec", method = RequestMethod.GET)
  public ResponseEntity<ArrayList<String>> recomendaciones(
      @RequestParam("url") String url,
      @RequestParam(value = "custom", required = false) String custom,
      @RequestParam(value = "expire", required = false) String expireDate,
      @RequestParam(value = "hasToken", required = false) String hasToken,
      HttpServletRequest request) {

    UrlValidator urlValidator = new UrlValidator(new String[] {"http", "https"});
    /*
     * Check if url comes through http or https
     */
    if (urlValidator.isValid(url)) {
      /*
       * Hash of URL or custom
       */
      String id;
      if (!custom.equals("")) {

        id = custom;

        if (shortURLRepository.findByHash(id) == null) {
          System.out.println("1");
          return new ResponseEntity<>(HttpStatus.CREATED);
        } else {
          System.out.println("2");
          try {
            HttpResponse<JsonNode> response =
                Unirest.get("https://wordsapiv1.p.mashape.com/words/" + id + "/synonyms")
                    .header("X-Mashape-Key", "VLzNEVr9zQmsh0gOlqs6wudMxDo1p1vCnjEjsnjNBhOCFeqLxr")
                    .header("Accept", "application/json")
                    .asJson();
            ObjectMapper map = new ObjectMapper();
            Synonym sin = map.readValue(response.getBody().toString(), Synonym.class);
            return new ResponseEntity<>(sin.getSynonyms(), HttpStatus.BAD_REQUEST);
          } catch (Exception e) {
            /*
             * Caso en el que la id seleccionada esta cogida y la
             * API no da alternativas
             */
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
          }
        }
      } else {
        return new ResponseEntity<>(HttpStatus.OK);
      }
    } else {
      System.out.println("3");
      return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
    }
  }
  /**
   * If shortURL is valid, creates it and saves it XXX: at the moment, it just ignores unknown
   * emails, with no feedback for users.
   */
  protected ShortURL createAndSaveIfValid(
      String url,
      String custom,
      String hasToken,
      String expireDate,
      String ip,
      String[] emails,
      Principal principal,
      String country) {

    UrlValidator urlValidator = new UrlValidator(new String[] {"http", "https"});
    /*
     * Check if url comes through http or https
     */
    if (urlValidator.isValid(url)) {
      logger.info("Shortening valid url " + url);
      /*
       * Creates a hash from the current date in case this is not custom
       */
      String id;
      String now = new Date().toString();
      if (custom.equals("")) {
        id = Hashing.murmur3_32().hashString(now, StandardCharsets.UTF_8).toString();
      } else {
        id = custom;
      }

      /*
       * Has Token
       */
      String token = null;
      if (hasToken != null && !hasToken.equals("")) {
        token = UUID.randomUUID().toString();
      }
      /*
       * Expire date
       */
      Date expire = null;
      if (!expireDate.equals("")) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        try {
          expire = sdf.parse(expireDate);
        } catch (ParseException e) {
          e.printStackTrace();
          logger.info("Error: badly introduced date.");
        }
      }

      /*
       * Checks every mail inserted by the user, and maintains a list with
       * those corresponding to registered users.
       */
      List<String> trueEmails = new ArrayList<String>();
      for (int i = 0; i < emails.length; i++) {
        if (!emails[i].equals("")) {
          User foundUser = null;

          foundUser = userRepository.findByMail(emails[i]);
          if (foundUser != null) {
            trueEmails.add(foundUser.getMail());
          }
        }
      }

      /*
       * If no valid emails are introduced, link will be public and it
       * wont have an email list.
       */
      boolean isPrivate = false;
      if (trueEmails.size() > 0) {
        isPrivate = true;
      } else {
        trueEmails = null;
      }

      /*
       * Gets email
       */
      String owner = getOwnerMail();

      /*
       * Creates ShortURL object
       */
      ShortURL su =
          new ShortURL(
              id,
              url,
              linkTo(
                      methodOn(UrlShortenerControllerWithLogs.class)
                          .redirectTo(id, null, null, null, null))
                  .toUri(),
              new Date(System.currentTimeMillis()),
              expire,
              owner,
              token,
              HttpStatus.TEMPORARY_REDIRECT.value(),
              ip,
              country,
              isPrivate,
              trueEmails);

      /*
       * Insert to DB
       */
      return shortURLRepository.save(su);
    } else {
      logger.info("Not valid url " + url);
      return null;
    }
  }
  @RequestMapping(value = "/{id:(?!link|index|profile).*}", method = RequestMethod.GET)
  public Object redirectTo(
      @PathVariable String id,
      @RequestParam(value = "token", required = false) String token,
      HttpServletResponse response,
      HttpServletRequest request,
      Model model) {

    logger.info("Requested redirection with hash " + id);
    ShortURL l = shortURLRepository.findByHash(id);
    logger.info("su: " + l);
    logger.info(l == null ? "null" : "not null");
    if (l != null) {
      /*
       * Check Token
       */
      if (l.getToken() != null && (token == null || !l.getToken().equals(token))) {
        /*
         * Wrong Token
         */
        response.setStatus(HttpStatus.BAD_REQUEST.value());
        throw new CustomException("400", "It is need a token");
      } else {

        Date d = new Date(System.currentTimeMillis());
        if (l.getExpire() != null && d.after(l.getExpire())) {
          /*
           * Date has expired
           */
          response.setStatus(HttpStatus.BAD_REQUEST.value());
          throw new CustomException("400", "Link has expired");

        } else {
          ArrayList<String> rules = l.getRules();
          if (rules != null && !rules.isEmpty()) {
            /*
             * Execute javascript
             */
            for (int i = 0; i < rules.size(); i++) {
              Boolean resul = executeS(rules.get(i), l);
              if (resul != null) {
                if (resul == true) {
                  response.setStatus(HttpStatus.BAD_REQUEST.value());
                  throw new CustomException("400", "Link has expired");
                }
              } else {
                response.setStatus(HttpStatus.BAD_REQUEST.value());
                throw new CustomException("400", "Bad rule");
              }
            }
          }

          List<String> authorizedMails = l.getAllowedUsers();
          if (authorizedMails != null && !authorizedMails.isEmpty()) {

            if (!authentication(authorizedMails)) {
              request.getSession().setAttribute("redirect", id);

              // model.addAttribute("hash", id);
              return "login_special";
            }
          }
          createAndSaveClick(id, request);
          long click =
              clickRepository.clicksByHash(l.getHash(), null, null, null, null, null, null);
          /* Data from countries */
          DBObject groupObject = clickRepository.getClicksByCountry(id, null, null).getRawResults();
          String list = groupObject.get("retval").toString();
          String countryData = StatsController.processCountryJSON(list);
          /* Data from cities */
          DBObject groupObjectCity =
              clickRepository
                  .getClicksByCity(id, null, null, null, null, null, null)
                  .getRawResults();
          String listCities = groupObjectCity.get("retval").toString();
          String cityData = StatsController.processCityJSON(listCities);
          WebSocketsData wb = new WebSocketsData(false, click, countryData, cityData);
          this.template.convertAndSend("/topic/" + id, wb);
          return createSuccessfulRedirectToResponse(l);
        }
      }
    } else {
      response.setStatus(HttpStatus.BAD_REQUEST.value());
      throw new CustomException("400", "BAD_REQUEST\nURL SHORTENED DOESN'T EXISTS");
    }
  }