/**
   * Update.
   *
   * @param request the request
   * @return the response
   */
  @RequestMapping(value = UPDATE, method = RequestMethod.POST)
  @ResponseBody
  public Response update(@RequestBody Map<String, Object> request) {
    ScheduleResponse response = new ScheduleResponse();

    try {
      ScheduleRequest scheduleRequest =
          new ScheduleRequest(new DMSchedule(Integer.parseInt(request.get(ID).toString())));

      // ADD user context to request
      addUserContextToRequest(scheduleRequest);

      response = getScheduleBCF().fetchScheduleById(scheduleRequest);
      if (!response.isOperationSuccess()) {
        return response;
      }

      DMSchedule schedule = response.getSchedules().get(0);

      if (STATUS_PAUSED.equals(request.get(TYPE))) {
        schedule.setStatusEnum(ScheduleStatusEnum.PAUSED);
      } else if (STATUS_RESUME.equals(request.get(TYPE))) {
        schedule.setStatusEnum(ScheduleStatusEnum.ENABLED);
      } else if (STATUS_FAILED.equals(request.get(TYPE))) {
        schedule.setStatusEnum(ScheduleStatusEnum.ENABLED);

        // New Next Execution Date
        Date serverUTC = DMConvertUtil.convertDateToDefaultUTC(new Date());

        // New Action Date = New Next Execution Date + (Old Action Date - Old Next Execution Date)
        Date actionDate =
            DMConvertUtil.convertDateToDefaultUTC(
                DMConvertUtil.convertIntegerToDate(
                    DMConvertUtil.convertDateToInteger(serverUTC)
                        + (DMConvertUtil.convertDateToInteger(
                                DMConvertUtil.convertDateToDefaultUTC(
                                    schedule.getDmAction().getActionTime()))
                            - DMConvertUtil.convertDateToInteger(
                                DMConvertUtil.convertDateToDefaultUTC(
                                    schedule.getFrequency().getNextExecution())))));

        schedule.getDmAction().setActionTime(actionDate);
        schedule.getFrequency().setNextExecution(serverUTC);
      }

      scheduleRequest.setSchedule(schedule);

      response = getScheduleBCF().updateScheduleStatus(scheduleRequest);

    } catch (Exception e) {
      SensusInterfaceUtil.handleException(
          LOG, response, e, DEFAULT_EXCEPTION_MSG, new String[] {CONTROLLER_EXCEPTION_MSG});
    }

    return response;
  }
 /**
  * Fill frequency.
  *
  * @param model the model
  * @param ends the ends
  * @param occurrences the occurrences
  * @param after the after
  * @param frequency the frequency
  * @param df the df
  * @throws Exception the exception
  */
 private void fillFrequency(
     ScheduleModel model,
     String ends,
     Integer occurrences,
     String after,
     Frequency frequency,
     DateFormat df,
     String timezone)
     throws Exception {
   if (!ends.equals(NEVER)) {
     frequency.setNeverEnds(false);
     if (ends.equals(AFTER)) {
       frequency.setEndsAfterOccurrences(occurrences);
     } else if (ends.equals(ON)) {
       frequency.setEndDate(
           DMConvertUtil.convertDateToUTC(
               df.parse(after + SPACE + model.getScheduleEventTime()), Integer.valueOf(timezone)));
     }
   } else {
     frequency.setNeverEnds(true);
   }
 }
  /**
   * Validation insert schedule.
   *
   * @param typeOperation the type operation
   * @param model the model
   * @return the schedule
   * @throws Exception the exception
   */
  public DMSchedule validationInsertSchedule(String typeOperation, ScheduleModel model)
      throws Exception {
    DMSchedule schedule = new DMSchedule();
    schedule.setName(model.getScheduledEventName());
    schedule.setDescription(model.getScheduledEventDescription());

    if (typeOperation.equals(UPDATE)) {
      model.setActionName(model.getActionTest());
    } else if (!ValidationUtil.isNullOrEmpty(model.getActionTest())) {
      model.setActionName(model.getActionTest());
    }

    Frequency frequency = new Frequency();
    frequency.setExecutedOccurrences(0);

    UserSettings userSettings = getUserSettings();

    List<Property> properties = new ArrayList<Property>();

    DMAction action = null;
    DateFormat df = getLocaleDateFormat(userSettings.getDateFormatMask());
    Date dateJavaHan;
    String defineEventWhen;

    if (ActionTypeEnum.INITIATE_DEMAND_RESPONSE_EVENT
        .getActionTypeName()
        .equals(model.getActionName())) {
      defineEventWhen = model.getDemandResponseWhen() + SPACE + model.getDemand_response_time();
    } else {
      defineEventWhen = model.getScheduledEventWhen() + SPACE + model.getScheduleEventTime();
    }

    Date dateJava = df.parse(defineEventWhen);

    // Frequency Date. When action is Demand Response or Send text message the frequency date is
    // equals schedule
    Date frequencyDate =
        DMConvertUtil.convertDateToUTC(
            dateJava, Integer.valueOf(userSettings.getTimeZoneMinutes()));

    if (model.getActionName().equals(ActionTypeEnum.SEND_HAN_TEXT_MESSAGE.getActionTypeName())) {
      SendHanTextMessageAction sendHanTextMessageAction = new SendHanTextMessageAction();
      sendHanTextMessageAction.setDurationHANTextMessage(model.getTextMessageDuration());
      sendHanTextMessageAction.setTextMessage(model.getTextMessageHan());

      if (SEND_LATER.equals(model.getPreProgram().get(0))) {

        String defineHanDate = model.getSendMessagesDate() + SPACE + model.getSendMessagesTime();

        if (!ValidationUtil.isNullOrEmpty(defineHanDate)) {
          dateJavaHan = df.parse(defineHanDate);

          sendHanTextMessageAction.setActionTime(
              DMConvertUtil.convertDateToUTC(
                  dateJava, Integer.valueOf(userSettings.getTimeZoneMinutes())));
          frequency.setNextExecution(
              DMConvertUtil.convertDateToUTC(
                  dateJavaHan, Integer.valueOf(userSettings.getTimeZoneMinutes())));
          schedule.setStartTime(
              DMConvertUtil.convertDateToUTC(
                  dateJavaHan, Integer.valueOf(userSettings.getTimeZoneMinutes())));
        }
      } else {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        dateJavaHan = calendar.getTime();
        sendHanTextMessageAction.setActionTime(
            DMConvertUtil.convertDateToUTC(
                dateJava, Integer.valueOf(userSettings.getTimeZoneMinutes())));
        frequency.setNextExecution(DMConvertUtil.convertDateToDefaultUTC(new Date()));
        schedule.setStartTime(DMConvertUtil.convertDateToDefaultUTC(new Date()));
      }

      frequencyDate = schedule.getStartTime();

      action = sendHanTextMessageAction;
    } else if (!ValidationUtil.isNullOrEmpty(model.getActionName())
        && model
            .getActionName()
            .equals(ActionTypeEnum.INITIATE_DEMAND_RESPONSE_EVENT.getActionTypeName())) {
      DemandResponseEventAction demandResponseEventAction = new DemandResponseEventAction();

      demandResponseEventAction.setDemandResponseDuration(model.getDemandResponseDuration());
      demandResponseEventAction.setEnrollmentCode(model.getEnrollmentCode());
      demandResponseEventAction.setHeating(model.getPctHeating());
      demandResponseEventAction.setCooling(model.getPctCooling());
      demandResponseEventAction.setDutyCycleRate(model.getDutyCycle());
      demandResponseEventAction.setLoadAdjustment(model.getLoadAdjustment());
      demandResponseEventAction.setCriticalityLevel(model.getHanCriticality());

      if (ValidationUtil.isNullOrEmpty(model.getHanStart())) {
        demandResponseEventAction.setRandomizeStart(Boolean.FALSE);
      } else if (model.getHanStart().equals(ON)) {
        demandResponseEventAction.setRandomizeStart(Boolean.TRUE);
      } else {
        demandResponseEventAction.setRandomizeStart(Boolean.FALSE);
      }

      if (ValidationUtil.isNullOrEmpty(model.getHanEnd())) {
        demandResponseEventAction.setRandomizeEnd(Boolean.FALSE);
      } else if (model.getHanEnd().equals(ON)) {
        demandResponseEventAction.setRandomizeEnd(Boolean.TRUE);
      } else {
        demandResponseEventAction.setRandomizeEnd(Boolean.FALSE);
      }

      if (!ValidationUtil.isNullOrEmpty(model.getHancheck())) {
        for (String id : model.getHancheck()) {
          if (id.equals(DeviceClassEnum.HVAC_COMPRESSOR.getValue())) {
            properties.add(new Property(DeviceClassEnum.HVAC_COMPRESSOR.toString(), TRUE));
          } else if (id.equals(DeviceClassEnum.STRIP_HEATER.getValue())) {
            properties.add(new Property(DeviceClassEnum.STRIP_HEATER.toString(), TRUE));
          } else if (id.equals(DeviceClassEnum.WATER_HEATER.getValue())) {
            properties.add(new Property(DeviceClassEnum.WATER_HEATER.toString(), TRUE));
          } else if (id.equals(DeviceClassEnum.POOL_PUMP.getValue())) {
            properties.add(new Property(DeviceClassEnum.POOL_PUMP.toString(), TRUE));
          } else if (id.equals(DeviceClassEnum.SMART_APPLIANCES.getValue())) {
            properties.add(new Property(DeviceClassEnum.SMART_APPLIANCES.toString(), TRUE));
          } else if (id.equals(DeviceClassEnum.IRRIGATION_PUMP.getValue())) {
            properties.add(new Property(DeviceClassEnum.IRRIGATION_PUMP.toString(), TRUE));
          } else if (id.equals(DeviceClassEnum.MANAGED_COMMERCIAL.getValue())) {
            properties.add(new Property(DeviceClassEnum.MANAGED_COMMERCIAL.toString(), TRUE));
          } else if (id.equals(DeviceClassEnum.SIMPLE_MISC.getValue())) {
            properties.add(new Property(DeviceClassEnum.SIMPLE_MISC.toString(), TRUE));
          } else if (id.equals(DeviceClassEnum.EXTERIOR_LIGHTING.getValue())) {
            properties.add(new Property(DeviceClassEnum.EXTERIOR_LIGHTING.toString(), TRUE));
          } else if (id.equals(DeviceClassEnum.INTERIOR_LIGHTING.getValue())) {
            properties.add(new Property(DeviceClassEnum.INTERIOR_LIGHTING.toString(), TRUE));
          } else if (id.equals(DeviceClassEnum.ELECTRIC_VEHICLE.getValue())) {
            properties.add(new Property(DeviceClassEnum.ELECTRIC_VEHICLE.toString(), TRUE));
          } else if (id.equals(DeviceClassEnum.GENERATION_SYSTEMS.getValue())) {
            properties.add(new Property(DeviceClassEnum.GENERATION_SYSTEMS.toString(), TRUE));
          }
        }
      }
      schedule.setProperties(properties);

      if (!ValidationUtil.isNull(model.getDemandResponseDate())
          && !ValidationUtil.isNull(model.getDemandResponseTime())) {
        String demandResponseDate =
            model.getDemandResponseDate() + SPACE + model.getDemandResponseTime();

        if (!ValidationUtil.isNullOrEmpty(demandResponseDate)) {
          dateJavaHan = df.parse(demandResponseDate);
          demandResponseEventAction.setActionTime(dateJava);
          frequency.setNextExecution(
              DMConvertUtil.convertDateToUTC(
                  dateJavaHan, Integer.valueOf(userSettings.getTimeZoneMinutes())));
          schedule.setStartTime(
              DMConvertUtil.convertDateToUTC(
                  dateJavaHan, Integer.valueOf(userSettings.getTimeZoneMinutes())));
        }
      }

      frequencyDate = schedule.getStartTime();

      action = demandResponseEventAction;
    } else {
      if (!ValidationUtil.isNullOrEmpty(model.getActionName())
          && model.getActionName().equals(ActionTypeEnum.REMOTE_ARM_CONNECT.getActionTypeName())) {
        action = new RemoteArmConnectAction();
      } else if (!ValidationUtil.isNullOrEmpty(model.getActionName())
          && model.getActionName().equals(ActionTypeEnum.REMOTE_CONNECT.getActionTypeName())) {
        action = new RemoteConnectAction();
      } else if (!ValidationUtil.isNullOrEmpty(model.getActionName())
          && model.getActionName().equals(ActionTypeEnum.REMOTE_DISCONNECT.getActionTypeName())) {
        action = new RemoteDisconnectAction();
      } else if (!ValidationUtil.isNullOrEmpty(model.getActionName())
          && model.getActionName().equals(ActionTypeEnum.DEMAND_READ.getActionTypeName())) {
        action = new DemandReadAction();
      } else {
        action = new DemandResetEventAction();
      }

      frequency.setNextExecution(
          DMConvertUtil.convertDateToUTC(
              dateJava, Integer.valueOf(userSettings.getTimeZoneMinutes())));
      schedule.setStartTime(
          DMConvertUtil.convertDateToUTC(
              dateJava, Integer.valueOf(userSettings.getTimeZoneMinutes())));
      action.setActionTime(
          DMConvertUtil.convertDateToUTC(
              dateJava, Integer.valueOf(userSettings.getTimeZoneMinutes())));
    }

    // Create the date in the format "00/00/0000 0:00am"
    schedule.setCreateDate(
        DMConvertUtil.convertDateToUTC(
            dateJava, Integer.valueOf(userSettings.getTimeZoneMinutes())));

    if (ValidationUtil.isNull(model.getRepeatCheckBox())) {
      model.setRepeatCheckBox(false);
    }

    if (model.getRepeatCheckBox()) {
      frequency.setFrequencyTypeEnum(FrequencyTypeEnum.enumForValue(model.getRepeatType()));

      if (!ValidationUtil.isNull(frequency.getFrequencyTypeEnum())) {

        frequency.setStartOnDate(frequencyDate);

        switch (frequency.getFrequencyTypeEnum()) {
          case DAILY:
            frequency.setTimeToRepeat(Integer.parseInt(model.getRepeatsEveryValueDaily()));
            fillFrequency(
                model,
                model.getEndsDaily(),
                model.getOccurrencesDaily(),
                model.getDateAfterDaily(),
                frequency,
                df,
                userSettings.getTimeZoneMinutes());

            break;

          case EVERY_WEEKDAY:
            fillFrequency(
                model,
                model.getEndsWeekday(),
                model.getOccurrencesWeekday(),
                model.getDateAfterWeekday(),
                frequency,
                df,
                userSettings.getTimeZoneMinutes());

            addDaysOfWeek(model, frequency, "2,3,4,5,6");

            break;

          case EVERY_MON_WED_FRI:
            fillFrequency(
                model,
                model.getEndsEveryOther(),
                model.getOccurrencesEveryOther(),
                model.getDateAfterEveryOther(),
                frequency,
                df,
                userSettings.getTimeZoneMinutes());

            addDaysOfWeek(model, frequency, "2,4,6");

            break;

          case EVERY_TUE_THURS:
            fillFrequency(
                model,
                model.getEndsEveryT(),
                model.getOccurrencesEveryT(),
                model.getDateAfterEveryT(),
                frequency,
                df,
                userSettings.getTimeZoneMinutes());

            addDaysOfWeek(model, frequency, "3,5");

            break;

          case WEEKLY:
            frequency.setTimeToRepeat(Integer.parseInt(model.getRepeatsEveryValueWeekly()));

            String[] weekDays = null;

            if (!ValidationUtil.isNullOrEmpty(model.getDayWeekly())) {
              weekDays = model.getDayWeekly().split(COMMA);

              frequency.setDaysOfWeeksEnum(new ArrayList<DaysOfWeekEnum>());

              for (String weekday : weekDays) {
                frequency
                    .getDaysOfWeeks()
                    .add(DaysOfWeekEnum.enumForValue(Integer.valueOf(weekday.trim())));
              }
            }

            fillFrequency(
                model,
                model.getEndsWeekly(),
                model.getOccurrencesWeekly(),
                model.getDateAfterWeekly(),
                frequency,
                df,
                userSettings.getTimeZoneMinutes());

            break;

          case MONTHLY:
            frequency.setTimeToRepeat(Integer.parseInt(model.getRepeatsEveryValueMonthly()));

            if (model.getRepeatByMonthly().equals("day-week")) {
              frequency.setDayOfWeek(true);
            } else if (model.getRepeatByMonthly().equals("date")) {
              frequency.setDayOfWeek(false);
            }

            fillFrequency(
                model,
                model.getEndsMonthly(),
                model.getOccurrencesMonthly(),
                model.getDateAfterMonthly(),
                frequency,
                df,
                userSettings.getTimeZoneMinutes());

            break;

          case YEARLY:
            frequency.setTimeToRepeat(Integer.parseInt(model.getRepeatsEveryValueYearly()));

            fillFrequency(
                model,
                model.getEndsYearly(),
                model.getOccurrencesYearly(),
                model.getDateAfterYearly(),
                frequency,
                df,
                userSettings.getTimeZoneMinutes());
            break;

          case CUSTOM:
            break;

          default:
            break;
        }
      } else {
        frequency.setFrequencyTypeEnum(FrequencyTypeEnum.NEVER);
      }
    } else {
      frequency.setFrequencyTypeEnum(FrequencyTypeEnum.NEVER);
    }

    schedule.setFrequency(frequency);

    schedule.setId(model.getScheduledEventId());

    if (!ValidationUtil.isNullOrEmpty(model.getGroupList())) {
      action.setGroups(new ArrayList<Group>());
      for (String groupId : model.getGroupList().split(COMMA)) {
        action.getGroups().add(new Group(new Integer(groupId.trim())));
      }
    } else {
      action.setGroups(null);
    }

    if (!ValidationUtil.isNullOrEmpty(model.getTagList())) {
      action.setTags(new ArrayList<Tag>());
      for (String tagId : model.getTagList().split(COMMA)) {
        action.addGroup(new Group(new Integer(tagId.trim())));
      }
    } else {
      action.setTags(null);
    }

    if (typeOperation.equals(INSERT)) {
      schedule.setModelAction(PersistanceActionEnum.INSERT);
    } else {
      schedule.setModelAction(PersistanceActionEnum.UPDATE);
      action.setId(model.getActionViewId());
    }

    action.setActionType(
        new ActionType(ActionTypeEnum.enumForValue(Integer.valueOf(model.getActionId()))));

    schedule.setStatusEnum(ScheduleStatusEnum.ENABLED);

    if (Boolean.TRUE.equals(model.getRecentRequestMonitor())) {
      action.setIsMonitored(Boolean.TRUE);
    } else {
      action.setIsMonitored(Boolean.FALSE);
    }

    action.setOnDemand(Boolean.FALSE);

    schedule.setDmAction(action);
    return schedule;
  }