/**
   * ******************************************************************
   *
   * <p>Decide on the campaign
   *
   * <p>The output could be one of 4 different messages depending on the day
   */
  public ActionInterface evaluate(
      PlayerInfo playerInfo,
      Timestamp executionTime,
      double responseFactor,
      ResponseStat response) {

    // System.out.println("Registration Date: " + getDay(user.created).toString());
    Timestamp executionDay = getDay(executionTime);
    User user = playerInfo.getUser();

    if (user.amount != 0 || user.sessions > 10) {

      System.out.println("    -- Campaign " + Name + " not Firing. Player already got going");
      return null;
    }

    int age = getDaysBetween(user.created, executionDay);

    if (age <= 2) {

      List<GameSession> sessions = playerInfo.getSessions();

      if (sessions.size() < 2 && age < 2) {

        GameRecommender recommender = new GameRecommender(playerInfo, executionTime);
        boolean hasTried = recommender.hasTried("os2x3x4x5x");

        if (!hasTried) {

          if (playerInfo.getUsageProfile().isMobilePlayer()) {

            // Send a mobile push
            System.out.println(
                "    -- Campaign " + Name + " mobile freespin get going " + user.name);
            return new MobilePushAction(
                    "Try a new Game. Here are some free spins for The 2x3x4x5x game",
                    user,
                    executionTime,
                    getPriority(),
                    getTag(),
                    Name,
                    305,
                    getState(),
                    responseFactor)
                .withReward(RewardRepository.OS2345Rest);
          }

          // Send a facebook push

          System.out.println("    -- Campaign " + Name + " fb freespin get going " + user.name);
          return new NotificationAction(
                  "There are many new games at SlotAmerica. Here are some free spins to try out the Old School 2x3x4x5x game",
                  user,
                  executionTime,
                  getPriority(),
                  getTag(),
                  Name,
                  5,
                  getState(),
                  responseFactor)
              .withReward(RewardRepository.OS2345Rest);
        }
      }

      System.out.println("    -- Campaign " + Name + " Running message 1 for " + user.name);

      if (playerInfo.getUsageProfile().isMobilePlayer()) {

        if (playerInfo.fallbackFromMobile()) {

          // TODO: Is there a point in adding an email here?
          System.out.println("    -- Campaign " + Name + " not firing. No mobile communication.");
          return null;
        }

        return new MobilePushAction(
            "An extra diamond for every day in a row you are playing!",
            user,
            executionTime,
            getPriority(),
            getTag(),
            Name,
            301,
            getState(),
            responseFactor);
      }

      int messageId = 83;
      if (!registeredInTheMorning(user)) messageId = 84;

      if (randomize4(user, 2) || randomize4(user, 4)) {

        return new NotificationAction(
            "The free coins are waiting. You get an extra diamond pick for every day in a row you are playing. Click here now!",
            user,
            executionTime,
            getPriority(),
            getTag(),
            Name,
            messageId,
            getState(),
            responseFactor);

      } else {

        System.out.println(
            "    -- Campaign " + Name + " not Firing. Player not in morning test (evening)");
        return null;
      }
    }

    if (age == 3 || age == 4) {

      System.out.println("    -- Campaign " + Name + " Running message 3 for " + user.name);

      if (playerInfo.getUsageProfile().isMobilePlayer() && !playerInfo.fallbackFromMobile()) {

        return new MobilePushAction(
            "We here at SlotAmerica are missing you! The thrilling slot machines are awaiting and you can use the FREE bonus to find your favorite game! Click here to get started",
            user,
            executionTime,
            getPriority(),
            getTag(),
            Name,
            302,
            getState(),
            responseFactor);
      }

      if (state == CampaignState.REDUCED) {

        System.out.println(
            "    -- Campaign " + Name + " not firing. Reduced mode remove low priority messages");
        return null;
      }

      return new NotificationAction(
          "We here at SlotAmerica are missing you! The thrilling slot machines are awaiting and you can use the FREE bonus to find your favorite game! Click here to get started",
          user,
          executionTime,
          getPriority(),
          getTag(),
          Name,
          2,
          getState(),
          responseFactor);
    }
    if (age == 5 || age == 6) {

      return new EmailAction(
          gettingStartedEmail1(user, createPromoCode(207)),
          user,
          executionTime,
          getPriority(),
          getTag(),
          207,
          getState(),
          responseFactor);
    }

    if (age == 7 || age == 8) {

      if (playerInfo.getUsageProfile().isMobilePlayer() && !playerInfo.fallbackFromMobile()) {

        return new MobilePushAction(
            "The games are waiting. Click here for your free bonus!",
            user,
            executionTime,
            getPriority(),
            getTag(),
            Name,
            303,
            getState(),
            responseFactor);
      }
    }

    if (age == 9 || age == 10) {

      if (playerInfo.getUsageProfile().isMobilePlayer() && !playerInfo.fallbackFromMobile()) {

        System.out.println(
            "    -- Campaign " + Name + " Pushing 8 day getting started message for " + user.name);
        return new MobilePushAction(
            "New game releases here at Slot America. Use your free bonus to try it out?",
            user,
            executionTime,
            getPriority(),
            getTag(),
            Name,
            304,
            getState(),
            responseFactor);
      }

      System.out.println(
          "    -- Campaign " + Name + " Emailing 8 day getting started message for " + user.name);
      return new EmailAction(
          gettingStartedEmail1(user, createPromoCode(204)),
          user,
          executionTime,
          getPriority(),
          getTag(),
          204,
          getState(),
          responseFactor);
    }

    if (age == 11 || age == 12) {

      System.out.println(
          "    -- Campaign " + Name + " Emailing 12 day getting started message for " + user.name);
      return new EmailAction(
          gettingStartedEmail1(user, createPromoCode(205)),
          user,
          executionTime,
          getPriority(),
          getTag(),
          205,
          getState(),
          responseFactor);
    }

    if (age == 15 || age == 16) {

      System.out.println(
          "    -- Campaign " + Name + " Emailing 16 day getting started message for " + user.name);
      return new EmailAction(
          gettingStartedEmail2(user, createPromoCode(206)),
          user,
          executionTime,
          getPriority(),
          getTag(),
          206,
          getState(),
          responseFactor);
    }

    System.out.println(
        "    -- Campaign "
            + Name
            + " not applicable for player "
            + user.name
            + ". Timing is not correct ( day = "
            + getDaysBetween(user.created, executionDay)
            + ")");
    return null;
  }
  /**
   * ************************************************************************
   *
   * <p>Decide on the campaign
   *
   * @param playerInfo - the user to evaluate
   * @param executionTime - when
   * @param responseFactor
   * @return - resulting action. (or null)
   */
  public ActionInterface evaluate(
      PlayerInfo playerInfo,
      Timestamp executionTime,
      double responseFactor,
      ResponseStat response) {

    Timestamp executionDay = getDay(executionTime);
    User user = playerInfo.getUser();

    if (user.sessions < ACTIVITY_MIN) {

      System.out.println(
          "    -- Campaign "
              + Name
              + " not active. Player has not been active enough ("
              + user.sessions
              + " sessions <  "
              + ACTIVITY_MIN);
      return null;
    }

    Timestamp lastSession = playerInfo.getLastMobileSession();
    if (lastSession == null) {

      System.out.println("    -- Campaign " + Name + " not firing. No sessions for user");
      return null;
    }
    int inactivity = getDaysBetween(lastSession, executionDay);

    if (user.payments == 0 && inactivity > INACTIVITY_LIMIT_FREE) {

      System.out.println(
          "    -- Campaign "
              + Name
              + " not active. Free player is inactive. ("
              + inactivity
              + " days >  "
              + INACTIVITY_LIMIT_FREE);
      return null;
    }

    if (user.payments > 0 && inactivity > INACTIVITY_LIMIT_PAYING) {

      System.out.println(
          "    -- Campaign "
              + Name
              + " not active. Paying player is inactive. ("
              + inactivity
              + " days >  "
              + INACTIVITY_LIMIT_PAYING);
      return null;
    }

    UsageProfileClassification classification = playerInfo.getUsageProfile();

    if (!classification.hasTriedMobile()) {

      System.out.println(
          "    -- Campaign "
              + Name
              + " not active. Not a mobile player. ( Classification: "
              + classification.name()
              + " )");
      return null;
    }

    boolean fallBackToMail = playerInfo.getCachedUserData().fallbackFromMobile();

    if (inactivity < 4) {

      System.out.println(
          "    -- Campaign "
              + Name
              + " Not firing. Waiting for inactivity...("
              + inactivity
              + "< 4)");
      return null;
    }

    if (inactivity > 4 && inactivity < 10) {

      if (fallBackToMail) {
        System.out.println("    -- Campaign " + Name + " firing (1) but falling back to mail. ");
        return new EmailAction(
            getMail1(user),
            user,
            executionTime,
            getPriority(),
            getTag(),
            201,
            getState(),
            responseFactor);
      }

      System.out.println("    -- Campaign " + Name + " firing (1) with a mobile push. ");
      return new MobilePushAction(
          "Hello, the games are awaiting you. Level up to take part of new benefits!",
          user,
          executionTime,
          getPriority(),
          getTag(),
          Name,
          301,
          getState(),
          responseFactor);
    }

    if (inactivity >= 10 && inactivity < 16) {

      System.out.println("    -- Campaign " + Name + " firing 10 day email ");
      return new EmailAction(
          getMail7(user, createPromoCode(207)),
          user,
          executionTime,
          getPriority(),
          getTag(),
          207,
          getState(),
          responseFactor);
    }

    if (inactivity >= 16 && inactivity < 24) {

      if (fallBackToMail) {
        System.out.println("    -- Campaign " + Name + " firing (2) but falling back to mail. ");
        return new EmailAction(
            getMail2(user),
            user,
            executionTime,
            getPriority(),
            getTag(),
            202,
            getState(),
            responseFactor);
      }

      System.out.println("    -- Campaign " + Name + " firing (2) with a mobile push. ");
      return new MobilePushAction(
          "What a lovely day for some exciting slots!",
          user,
          executionTime,
          getPriority(),
          getTag(),
          Name,
          302,
          getState(),
          responseFactor);
    }

    if (inactivity >= 24 && inactivity < 32) {

      if (fallBackToMail) {
        System.out.println("    -- Campaign " + Name + " firing (3) but falling back to mail. ");
        return new EmailAction(
                getMail3(user),
                user,
                executionTime,
                getPriority(),
                getTag(),
                203,
                getState(),
                responseFactor)
            .attach(
                new GiveCoinAction(
                    2000,
                    user,
                    executionTime,
                    getPriority(),
                    Name,
                    203,
                    getState(),
                    responseFactor));
      }
      System.out.println("    -- Campaign " + Name + " firing (3) with a mobile push. ");
      return new MobilePushAction(
              "We have added 2000 extra coins to your account!",
              user,
              executionTime,
              getPriority(),
              getTag(),
              Name,
              303,
              getState(),
              responseFactor)
          .attach(
              new GiveCoinAction(
                  2000, user, executionTime, getPriority(), Name, 303, getState(), responseFactor));
    }

    if (inactivity >= 32 && inactivity < 40) {

      if (fallBackToMail) {
        System.out.println("    -- Campaign " + Name + " firing (4) but falling back to mail. ");
        return new EmailAction(
            getMail4(user),
            user,
            executionTime,
            getPriority(),
            getTag(),
            204,
            getState(),
            responseFactor);
      }
      System.out.println("    -- Campaign " + Name + " firing (4) with a mobile push. ");
      return new MobilePushAction(
          "There are new games released! Come in and check them out!",
          user,
          executionTime,
          getPriority(),
          getTag(),
          Name,
          304,
          getState(),
          responseFactor);
    }

    if (inactivity >= 40 && inactivity < 48) {

      if (fallBackToMail) {
        System.out.println("    -- Campaign " + Name + " firing (5) but falling back to mail. ");
        return new EmailAction(
            getMail5(user),
            user,
            executionTime,
            getPriority(),
            getTag(),
            205,
            getState(),
            responseFactor);
      }

      System.out.println("    -- Campaign " + Name + " firing (5) with a mobile push. ");
      return new MobilePushAction(
          "There are new games released! Come in and check them out!",
          user,
          executionTime,
          getPriority(),
          getTag(),
          Name,
          305,
          getState(),
          responseFactor);
    }

    if (inactivity >= 48) {

      System.out.println("    -- Campaign " + Name + " firing (6) - email. ");
      return new EmailAction(
          getMail6(user),
          user,
          executionTime,
          getPriority(),
          getTag(),
          206,
          getState(),
          responseFactor);
    }

    System.out.println("    -- Campaign " + Name + " Not firing, inactive too long ");

    return null;
  }