/* (non-Javadoc)
   * <p>Title: doMonitoring</p>
   * <p>Description: </p>
   * @see auto_scaling.monitor.Monitor#doMonitoring()
   */
  @Override
  public void doMonitoring() {
    SystemStatus systemStatus = SystemStatus.getSystemStatus();
    Collection<InstanceStatus> instances =
        InstanceFilter.getAttachedInstances(systemStatus.getAllInstances());

    ApplicationBrokerManager applicationBrokerManager =
        ApplicationBrokerManager.getApplicationBrokerManager();
    CloudSimBroker cloudSimBroker = applicationBrokerManager.getCloudSimBroker();

    String CPU = ResourceType.CPU.getName();
    for (InstanceStatus instanceStatus : instances) {
      String idString = instanceStatus.getId();
      MonitoredVMex vm = (MonitoredVMex) cloudSimBroker.getVmById(Integer.parseInt(idString));
      double utilization = vm.getCPUUtil();
      instanceStatus.setResourceConsumptionValue(CPU, utilization);
    }

    if (instances.size() > 0) {
      EventGenerator eventGenerator = EventGenerator.getEventGenerator();
      Map<String, Object> data = new HashMap<String, Object>();
      data.put(EventDataName.RESOURCE_TYPE, ResourceType.CPU);
      Event newEvent = eventGenerator.generateEvent(Events.RESOURCE_REQUIREMENT_UPDATE_EVENT, data);

      Queue<Event> eventQueue = EventQueueManager.getEventsQueue();
      eventQueue.add(newEvent);
      monitorLog.info(logFormatter.getGenerateEventLogString(newEvent, CPU));
    }
  }
  /**
   * @Title: getNominalChosenSpotGroup @Description: get all instances can be potential capacity in
   * a spot group
   *
   * @param instanceTemplate the spot group
   * @return all instances can be potential capacity in a spot group
   * @throws
   */
  public synchronized Collection<InstanceStatus> getNominalChosenSpotGroup(
      InstanceTemplate instanceTemplate) {
    Set<InstanceStatus> group = spotGroups.get(instanceTemplate);
    if (group != null) {
      return InstanceFilter.getNominalInstances(snapshot(group));
    }

    return null;
  }
 /**
  * @Title: getNominalSpotGroups @Description: get all instances in spot groups that can be
  * potential capacity
  *
  * @return all instances in spot groups that can be potential capacity
  * @throws
  */
 public synchronized Map<InstanceTemplate, Collection<InstanceStatus>> getNominalSpotGroups() {
   Map<InstanceTemplate, Collection<InstanceStatus>> nominalSpotGroupsMap =
       new HashMap<InstanceTemplate, Collection<InstanceStatus>>();
   Map<InstanceTemplate, Set<InstanceStatus>> spotGroups = getSpotGroups();
   for (Entry<InstanceTemplate, Set<InstanceStatus>> entry : spotGroups.entrySet()) {
     nominalSpotGroupsMap.put(
         entry.getKey(), InstanceFilter.getNominalInstances(entry.getValue()));
   }
   return nominalSpotGroupsMap;
 }
  /**
   * @Title: getRunningInstancesIds @Description: get all running instances' ids
   *
   * @return all running instances' ids
   * @throws
   */
  public synchronized Collection<String> getRunningInstancesIds() {
    List<String> instanceIds = new ArrayList<String>();
    Collection<InstanceStatus> runningInstances = InstanceFilter.getRunningInstances(allInstances);

    for (InstanceStatus instanceStatus : runningInstances) {
      instanceIds.add(instanceStatus.getId());
    }

    return instanceIds;
  }
  /**
   * @Title: getMaximumAvaliableCapacity @Description: get the number of maximum capacity
   *
   * @return the number of maximum capacity
   * @throws
   */
  public synchronized long getMaximumAvaliableCapacity() {
    long capacity = 0;
    Collection<InstanceStatus> attachedInstances =
        InstanceFilter.getAttachedInstances(allInstances);
    for (InstanceStatus instanceStatus : attachedInstances) {

      InstanceTemplate instanceTemplate = instanceStatus.getType();
      capacity += instanceTemplate.getMaximunCapacity();
    }
    return capacity;
  }
  /**
   * @Title: getNominalCapacity @Description: get the number of capacity if all nominal instances
   * are online
   *
   * @return
   * @throws
   */
  public synchronized long getNominalCapacity() {
    FaultTolerantLevel ftLevel = FaultTolerantLevel.ZERO;
    if (isSpotEnabled()) {
      ftLevel = this.faultTolerantLevel;
    }

    long capacity = 0;
    Collection<InstanceStatus> nominalInstances = InstanceFilter.getNominalInstances(allInstances);

    for (InstanceStatus instanceStatus : nominalInstances) {
      InstanceTemplate instanceTemplate = instanceStatus.getType();
      capacity += instanceTemplate.getCapacity(ftLevel);
    }
    return capacity;
  }
  /**
   * @Title: getAvailableCapacity @Description: get the number of current capacity
   *
   * @return the number of current capacity
   * @throws
   */
  public synchronized long getAvailableCapacity() {
    FaultTolerantLevel ftLevel = FaultTolerantLevel.ZERO;
    if (isSpotEnabled()) {
      ftLevel = this.faultTolerantLevel;
    }

    long capacity = 0;
    Collection<InstanceStatus> attachedInstances =
        InstanceFilter.getAttachedInstances(allInstances);
    for (InstanceStatus instanceStatus : attachedInstances) {

      InstanceTemplate instanceTemplate = instanceStatus.getType();
      if (instanceStatus instanceof OnDemandInstanceStatus) {
        capacity += instanceTemplate.getCapacity(FaultTolerantLevel.ZERO);
      } else {
        capacity += instanceTemplate.getCapacity(ftLevel);
      }
    }
    return capacity;
  }
 /**
  * @Title: getNumOfAttachedInstances @Description: get the number of instances attached to the
  * load balancer
  *
  * @return
  * @throws
  */
 public synchronized int getNumOfAttachedInstances() {
   Collection<InstanceStatus> attachedInstances =
       InstanceFilter.getAttachedInstances(allInstances);
   return attachedInstances.size();
 }
 /**
  * @Title: getNominalOnDemandInstances @Description: get all on demand instances can be potential
  * capacity
  *
  * @return all on demand instances can be potential capacity
  * @throws
  */
 public synchronized Collection<InstanceStatus> getNominalOnDemandInstances() {
   return InstanceFilter.getNominalInstances(new ArrayList<InstanceStatus>(onDemandInstances));
 }