/**
  * Synchroneous method to load the image. It should only be called by something which is a thread
  * itself such as the HtmlDistillerThread. Since this intended for large batch operations this
  * bypasses the cache.
  *
  * @param imageUrl The Url of the image to be loaded
  * @param rotation The angle by which it is to be roated upon loading.
  */
 public void loadPictureImd(URL imageUrl, double rotation) {
   Tools.log("loadPictureImd invoked with URL: " + imageUrl.toString());
   if (sourcePicture != null) sourcePicture.removeListener(this);
   sourcePicture = new SourcePicture();
   sourcePicture.addListener(this);
   setStatus(LOADING, "Loading: " + imageUrl.toString());
   scaleAfterLoad = true;
   sourcePicture.loadPicture(imageUrl, rotation);
 }
  /**
   * Method that sets the status of the ScalablePicture object and notifies intereasted objects of a
   * change in status (not built yet).
   */
  private void setStatus(int statusCode, String statusMessage) {
    String filename = (imageUrl == null) ? "" : imageUrl.toString();
    Tools.log(
        "ScalablePicture.setStatus: sending: "
            + statusMessage
            + " to all Listeners from Image: "
            + filename);

    pictureStatusCode = statusCode;
    pictureStatusMessage = statusMessage;

    Enumeration e = scalablePictureStatusListeners.elements();
    while (e.hasMoreElements()) {
      ((ScalablePictureListener) e.nextElement())
          .scalableStatusChange(pictureStatusCode, pictureStatusMessage);
    }
  }
  /**
   * method that is invoked by the SourcePictureListener interface. Usually this will be called by
   * the SourcePicture telling the ScalablePicture that it has completed loading. The
   * ScalablePicture should then change it's own status and tell the ScalableListeners what's up.
   */
  public void sourceStatusChange(int statusCode, String statusMessage, SourcePicture sp) {
    // Tools.log("ScalablePicture.sourceStatusChange: status received from SourceImage: " +
    // statusMessage);

    switch (statusCode) {
      case SourcePicture.UNINITIALISED:
        Tools.log(
            "ScalablePicture.sourceStatusChange: pictureStatus was: UNINITIALISED message: "
                + statusMessage);
        setStatus(UNINITIALISED, statusMessage);
        break;
      case SourcePicture.ERROR:
        Tools.log(
            "ScalablePicture.sourceStatusChange: pictureStatus was: ERROR message: "
                + statusMessage);
        setStatus(ERROR, statusMessage);
        sourcePicture.removeListener(this);
        break;
      case SourcePicture.LOADING:
        Tools.log(
            "ScalablePicture.sourceStatusChange: pictureStatus was: LOADING message: "
                + statusMessage);
        setStatus(LOADING, statusMessage);
        break;
      case SourcePicture.ROTATING:
        Tools.log(
            "ScalablePicture.sourceStatusChange: pictureStatus was: ROTATING message: "
                + statusMessage);
        setStatus(LOADING, statusMessage);
        break;
      case SourcePicture.READY:
        Tools.log(
            "ScalablePicture.sourceStatusChange: pictureStatus was: READY message: "
                + statusMessage);
        setStatus(LOADED, statusMessage);
        sourcePicture.removeListener(this);
        if (scaleAfterLoad) {
          createScaledPictureInThread(Thread.MAX_PRIORITY);
          scaleAfterLoad = false;
        }
        break;
      default:
        Tools.log(
            "ScalablePicture.sourceStatusChange: Don't recognize this status: " + statusMessage);
        break;
    }
  }
  /**
   * method to invoke with a filename or URL of a picture that is to be loaded and scaled in a new
   * thread. This is handy to update the screen while the loading chuggs along in the background.
   * Make sure you invoked setScaleFactor or setScaleSize before invoking this method.
   *
   * <p>Step 1: Am I already loading what I need somewhere? If yes -> use it. Has it finished
   * loading? If no -> wait for it If yes -> use it Else -> load it
   *
   * @param priority The Thread priority
   * @param imageUrl The URL of the image you want to load
   * @param rotation The rotation 0-360 that the image should be put through after loading.
   */
  public void loadAndScalePictureInThread(URL imageUrl, int priority, double rotation) {
    this.imageUrl = imageUrl;

    boolean alreadyLoading = false;
    Tools.log(
        "ScalablePicture.loadAndScalePictureInThread: checking if picture "
            + imageUrl
            + " is already being loaded.");
    if ((sourcePicture != null)
        && (sourcePicture.getUrl().toString().equals(imageUrl.toString()))) {
      Tools.log(
          "ScalablePicture.loadAndScalePictureInThread: the SourcePicture is already loading the sourcePictureimage");
      alreadyLoading = true;
    } else if (PictureCache.isInCache(imageUrl)) {
      // in case the old image has a listener connected remove it
      //  fist time round the sourcePicture is still null therefore the if.
      if (sourcePicture != null) sourcePicture.removeListener(this);

      sourcePicture = PictureCache.getSourcePicture(imageUrl);
      String status = sourcePicture.getStatusMessage();
      if (status == null) status = "";
      Tools.log("ScalablePicture.loadAndScalePictureInThread: Picture in cache! Status: " + status);

      if (sourcePicture.getRotation() == rotation) {
        alreadyLoading = true;
        Tools.log(
            "ScalablePicture.loadAndScalePictureInThread: Picture was even rotated to the correct angle!");
      } else {
        alreadyLoading = false;
        Tools.log(
            "ScalablePicture.loadAndScalePictureInThread: Picture was in cache but with wrong rotation. Forcing reload.");
      }
    }

    if (alreadyLoading) {
      switch (sourcePicture.getStatusCode()) {
        case SourcePicture.UNINITIALISED:
          alreadyLoading = false;
          Tools.log(
              "ScalablePicture.loadAndScalePictureInThread: pictureStatus was: UNINITIALISED");
          break;
        case SourcePicture.ERROR:
          alreadyLoading = false;
          Tools.log("ScalablePicture.loadAndScalePictureInThread: pictureStatus was: ERROR");
          break;
        case SourcePicture.LOADING:
          Tools.log("ScalablePicture.loadAndScalePictureInThread: pictureStatus was: LOADING");
          sourcePicture.addListener(this);
          setStatus(LOADING, "Loading: " + imageUrl.toString());
          sourceLoadProgressNotification(
              SourcePicture.LOADING_PROGRESS, sourcePicture.getPercentLoaded());
          scaleAfterLoad = true;
          break;
        case SourcePicture.ROTATING:
          Tools.log("ScalablePicture.loadAndScalePictureInThread: pictureStatus was: ROTATING");
          setStatus(LOADING, "Rotating: " + imageUrl.toString());
          sourceLoadProgressNotification(
              SourcePicture.LOADING_PROGRESS, sourcePicture.getPercentLoaded());
          scaleAfterLoad = true;
          break;
        case SourcePicture.READY:
          Tools.log(
              "ScalablePicture.loadAndScalePictureInThread: pictureStatus was: READY. Sending SCALING status.");
          setStatus(SCALING, "Scaling: " + imageUrl.toString());
          createScaledPictureInThread(priority);
          break;
        default:
          Tools.log(
              "ScalablePicture.loadAndScalePictureInThread: Don't know what status this is:"
                  + Integer.toString(sourcePicture.getStatusCode()));
          break;
      }
    }

    // if the image is not already there then load it.
    if (!alreadyLoading) {
      if (sourcePicture != null) sourcePicture.removeListener(this);
      sourcePicture = new SourcePicture();
      sourcePicture.addListener(this);
      setStatus(LOADING, "Loading: " + imageUrl.toString());
      scaleAfterLoad = true;
      sourcePicture.loadPictureInThread(imageUrl, priority, rotation);
      // when the thread is done it sends a sourceStatusChange message to us
    }
  }