/**
   * Pauses execution of a cloudlet.
   *
   * @param cloudletId ID of the cloudlet being paused
   * @return $true if cloudlet paused, $false otherwise
   * @pre $none
   * @post $none
   */
  @Override
  public boolean cloudletPause(int cloudletId) {
    boolean found = false;
    int position = 0;

    // first, looks for the cloudlet in the exec list
    for (ResCloudlet rcl : getCloudletExecList()) {
      if (rcl.getCloudletId() == cloudletId) {
        found = true;
        break;
      }
      position++;
    }

    if (found) {
      // moves to the paused list
      ResCloudlet rgl = getCloudletExecList().remove(position);
      if (rgl.getRemainingCloudletLength() == 0) {
        cloudletFinish(rgl);
      } else {
        rgl.setCloudletStatus(Cloudlet.PAUSED);
        getCloudletPausedList().add(rgl);
      }
      return true;
    }

    // now, look for the cloudlet in the waiting list
    position = 0;
    found = false;
    for (ResCloudlet rcl : getCloudletWaitingList()) {
      if (rcl.getCloudletId() == cloudletId) {
        found = true;
        break;
      }
      position++;
    }

    if (found) {
      // moves to the paused list
      ResCloudlet rgl = getCloudletWaitingList().remove(position);
      if (rgl.getRemainingCloudletLength() == 0) {
        cloudletFinish(rgl);
      } else {
        rgl.setCloudletStatus(Cloudlet.PAUSED);
        getCloudletPausedList().add(rgl);
      }
      return true;
    }

    return false;
  }
  /**
   * Cancels execution of a cloudlet.
   *
   * @param cloudletId ID of the cloudlet being cancealed
   * @return the canceled cloudlet, $null if not found
   * @pre $none
   * @post $none
   */
  @Override
  public Cloudlet cloudletCancel(int cloudletId) {
    // First, looks in the finished queue
    for (ResCloudlet rcl : getCloudletFinishedList()) {
      if (rcl.getCloudletId() == cloudletId) {
        getCloudletFinishedList().remove(rcl);
        return rcl.getCloudlet();
      }
    }

    // Then searches in the exec list
    for (ResCloudlet rcl : getCloudletExecList()) {
      if (rcl.getCloudletId() == cloudletId) {
        getCloudletExecList().remove(rcl);
        if (rcl.getRemainingCloudletLength() == 0) {
          cloudletFinish(rcl);
        } else {
          rcl.setCloudletStatus(Cloudlet.CANCELED);
        }
        return rcl.getCloudlet();
      }
    }

    // Now, looks in the paused queue
    for (ResCloudlet rcl : getCloudletPausedList()) {
      if (rcl.getCloudletId() == cloudletId) {
        getCloudletPausedList().remove(rcl);
        return rcl.getCloudlet();
      }
    }

    // Finally, looks in the waiting list
    for (ResCloudlet rcl : getCloudletWaitingList()) {
      if (rcl.getCloudletId() == cloudletId) {
        rcl.setCloudletStatus(Cloudlet.CANCELED);
        getCloudletWaitingList().remove(rcl);
        return rcl.getCloudlet();
      }
    }

    return null;
  }
  /**
   * Gets the status of a cloudlet.
   *
   * @param cloudletId ID of the cloudlet
   * @return status of the cloudlet, -1 if cloudlet not found
   * @pre $none
   * @post $none
   */
  @Override
  public int getCloudletStatus(int cloudletId) {
    for (ResCloudlet rcl : getCloudletExecList()) {
      if (rcl.getCloudletId() == cloudletId) {
        return rcl.getCloudletStatus();
      }
    }

    for (ResCloudlet rcl : getCloudletPausedList()) {
      if (rcl.getCloudletId() == cloudletId) {
        return rcl.getCloudletStatus();
      }
    }

    for (ResCloudlet rcl : getCloudletWaitingList()) {
      if (rcl.getCloudletId() == cloudletId) {
        return rcl.getCloudletStatus();
      }
    }

    return -1;
  }
  /**
   * Resumes execution of a paused cloudlet.
   *
   * @param cloudletId ID of the cloudlet being resumed
   * @return $true if the cloudlet was resumed, $false otherwise
   * @pre $none
   * @post $none
   */
  @Override
  public double cloudletResume(int cloudletId) {
    boolean found = false;
    int position = 0;

    // look for the cloudlet in the paused list
    for (ResCloudlet rcl : getCloudletPausedList()) {
      if (rcl.getCloudletId() == cloudletId) {
        found = true;
        break;
      }
      position++;
    }

    if (found) {
      ResCloudlet rcl = getCloudletPausedList().remove(position);

      // it can go to the exec list
      if ((currentCpus - usedPes) >= rcl.getNumberOfPes()) {
        rcl.setCloudletStatus(Cloudlet.INEXEC);
        for (int i = 0; i < rcl.getNumberOfPes(); i++) {
          rcl.setMachineAndPeId(0, i);
        }

        long size = rcl.getRemainingCloudletLength();
        size *= rcl.getNumberOfPes();
        rcl.getCloudlet().setCloudletLength(size);

        getCloudletExecList().add(rcl);
        usedPes += rcl.getNumberOfPes();

        // calculate the expected time for cloudlet completion
        double capacity = 0.0;
        int cpus = 0;
        for (Double mips : getCurrentMipsShare()) {
          capacity += mips;
          if (mips > 0) {
            cpus++;
          }
        }
        currentCpus = cpus;
        capacity /= cpus;

        long remainingLength = rcl.getRemainingCloudletLength();
        double estimatedFinishTime =
            CloudSim.clock() + (remainingLength / (capacity * rcl.getNumberOfPes()));

        return estimatedFinishTime;
      } else { // no enough free PEs: go to the waiting queue
        rcl.setCloudletStatus(Cloudlet.QUEUED);

        long size = rcl.getRemainingCloudletLength();
        size *= rcl.getNumberOfPes();
        rcl.getCloudlet().setCloudletLength(size);

        getCloudletWaitingList().add(rcl);
        return 0.0;
      }
    }

    // not found in the paused list: either it is in in the queue, executing or not exist
    return 0.0;
  }