text: /**
   * Plugin.js
   *
   * Released under LGPL License.
   * Copyright (c) 1999-2016 Ephox Corp. All rights reserved
   *
   * License: http://www.tinymce.com/license
   * Contributing: http://www.tinymce.com/contributing
   */
  
  /**
   *
   * Settings:
   *  imagetools_cors_hosts - Array of remote domains that has CORS setup.
   *  imagetools_proxy - Url to proxy that streams images from remote host to local host.
   *  imagetools_toolbar - Toolbar items to render when an editable image is selected.
   */
  define("tinymce/imagetoolsplugin/Plugin", [
      "global!tinymce.PluginManager",
      "global!tinymce.Env",
      "global!tinymce.util.Promise",
      "global!tinymce.util.URI",
      "global!tinymce.util.Tools",
      "global!tinymce.util.Delay",
      "ephox/imagetools/api/ImageTransformations",
      "ephox/imagetools/api/BlobConversions",
      "tinymce/imagetoolsplugin/Dialog",
      "tinymce/imagetoolsplugin/ImageSize",
      "tinymce/imagetoolsplugin/Proxy"
  ], function (PluginManager, Env, Promise, URI, Tools, Delay, ImageTransformations, BlobConversions, Dialog, ImageSize, Proxy) {
      var plugin = function (editor) {
          var count = 0, imageUploadTimer, lastSelectedImage;
  
          if (!Env.fileApi) {
              return;
          }
  
          function displayError(error) {
              editor.notificationManager.open({
                  text: error,
                  type: 'error'
              });
          }
  
          function getSelectedImage() {
              return editor.selection.getNode();
          }
  
          function createId() {
              return 'imagetools' + count++;
          }
  
          function isLocalImage(img) {
              var url = img.src;
  
              return url.indexOf('data:') === 0 || url.indexOf('blob:') === 0 || new URI(url).host === editor.documentBaseURI.host;
          }
  
          function isCorsImage(img) {
              return Tools.inArray(editor.settings.imagetools_cors_hosts, new URI(img.src).host) !== -1;
          }
  
          function getApiKey() {
              return editor.settings.api_key || editor.settings.imagetools_api_key;
          }
  
          function imageToBlob(img) {
              var src = img.src, apiKey;
  
              if (isCorsImage(img)) {
                  return Proxy.getUrl(img.src, null);
              }
  
              if (!isLocalImage(img)) {
                  src = editor.settings.imagetools_proxy;
                  src += (src.indexOf('?') === -1 ? '?' : '&') + 'url=' + encodeURIComponent(img.src);
                  apiKey = getApiKey();
                  return Proxy.getUrl(src, apiKey);
              }
  
              return BlobConversions.imageToBlob(img);
          }
  
          function findSelectedBlob() {
              var blobInfo;
  
              blobInfo = editor.editorUpload.blobCache.getByUri(getSelectedImage().src);
              if (blobInfo) {
                  return blobInfo.blob();
              }
  
              return imageToBlob(getSelectedImage());
          }
  
          function startTimedUpload() {
              imageUploadTimer = Delay.setEditorTimeout(editor, function () {
                  editor.editorUpload.uploadImagesAuto();
              }, 30000);
          }
  
          function cancelTimedUpload() {
              clearTimeout(imageUploadTimer);
          }
  
          function updateSelectedImage(blob, uploadImmediately) {
              return BlobConversions.blobToDataUri(blob).then(function (dataUri) {
                  var id, base64, blobCache, blobInfo, selectedImage;
  
                  selectedImage = getSelectedImage();
                  id = createId();
                  blobCache = editor.editorUpload.blobCache;
                  base64 = URI.parseDataUri(dataUri).data;
  
                  blobInfo = blobCache.create(id, blob, base64);
                  blobCache.add(blobInfo);
  
                  editor.undoManager.transact(function () {
                      function imageLoadedHandler() {
                          editor.$(selectedImage).off('load', imageLoadedHandler);
                          editor.nodeChanged();
  
                          if (uploadImmediately) {
                              editor.editorUpload.uploadImagesAuto();
                          } else {
                              cancelTimedUpload();
                              startTimedUpload();
                          }
                      }
  
                      editor.$(selectedImage).on('load', imageLoadedHandler);
  
                      editor.$(selectedImage).attr({
                          src: blobInfo.blobUri()
                      }).removeAttr('data-mce-src');
                  });
  
                  return blobInfo;
              });
          }
  
          function selectedImageOperation(fn) {
              return function () {
                  return editor._scanForImages().then(findSelectedBlob).then(fn).then(updateSelectedImage, displayError);
              };
          }
  
          function rotate(angle) {
              return function () {
                  return selectedImageOperation(function (blob) {
                      var size = ImageSize.getImageSize(getSelectedImage());
  
                      if (size) {
                          ImageSize.setImageSize(getSelectedImage(), {
                              w: size.h,
                              h: size.w
                          });
                      }
  
                      return ImageTransformations.rotate(blob, angle);
                  })();
              };
          }
  
          function flip(axis) {
              return function () {
                  return selectedImageOperation(function (blob) {
                      return ImageTransformations.flip(blob, axis);
                  })();
              };
          }
  
          function editImageDialog() {
              var img = getSelectedImage(), originalSize = ImageSize.getNaturalImageSize(img);
              var handleDialogBlob = function (blob) {
                  return new Promise(function (resolve) {
                      BlobConversions.blobToImage(blob).then(function (newImage) {
                          var newSize = ImageSize.getNaturalImageSize(newImage);
  
                          if (originalSize.w != newSize.w || originalSize.h != newSize.h) {
                              if (ImageSize.getImageSize(img)) {
                                  ImageSize.setImageSize(img, newSize);
                              }
                          }
  
                          URL.revokeObjectURL(newImage.src);
                          resolve(blob);
                      });
                  });
              };
  
              var openDialog = function (blob) {
                  return Dialog.edit(blob).then(handleDialogBlob).then(function (blob) {
                      updateSelectedImage(blob, true);
                  }, function () {
                      // Close dialog
                  });
              };
  
              if (img) {
                  imageToBlob(img).then(openDialog, displayError);
              }
          }
  
          function addButtons() {
              editor.addButton('rotateleft', {
                  title: 'Rotate counterclockwise',
                  onclick: rotate(-90)
              });
  
              editor.addButton('rotateright', {
                  title: 'Rotate clockwise',
                  onclick: rotate(90)
              });
  
              editor.addButton('flipv', {
                  title: 'Flip vertically',
                  onclick: flip('v')
              });
  
              editor.addButton('fliph', {
                  title: 'Flip horizontally',
                  onclick: flip('h')
              });
  
              editor.addButton('editimage', {
                  title: 'Edit image',
                  onclick: editImageDialog
              });
  
              editor.addButton('imageoptions', {
                  title: 'Image options',
                  icon: 'options',
                  cmd: 'mceImage'
              });
  
              /*
              editor.addButton('crop', {
                  title: 'Crop',
                  onclick: startCrop
              });
              */
          }
  
          function addEvents() {
              editor.on('NodeChange', function (e) {
                  //If the last node we selected was an image
                  //And had a source that doesn't match the current blob url
                  //We need to attempt to upload it
                  if (lastSelectedImage && lastSelectedImage.src != e.element.src) {
                      cancelTimedUpload();
                      editor.editorUpload.uploadImagesAuto();
                      lastSelectedImage = undefined;
                  }
  
                  //Set up the lastSelectedImage
                  if (isEditableImage(e.element)) {
                      lastSelectedImage = e.element;
                  }
              });
          }
  
          function isEditableImage(img) {
              var selectorMatched = editor.dom.is(img, 'img:not([data-mce-object],[data-mce-placeholder])');
  
              return selectorMatched && (isLocalImage(img) || isCorsImage(img) || editor.settings.imagetools_proxy);
          }
  
          function addToolbars() {
              var toolbarItems = editor.settings.imagetools_toolbar;
  
              if (!toolbarItems) {
                  toolbarItems = 'rotateleft rotateright | flipv fliph | crop editimage imageoptions';
              }
  
              editor.addContextToolbar(
                  isEditableImage,
                  toolbarItems
              );
          }
  
          addButtons();
          addToolbars();
          addEvents();
  
          editor.addCommand('mceEditImage', editImageDialog);
      };
  
      PluginManager.add('imagetools', plugin);
  
      return function () {
      };
  });
  