Editor.Control = {}

Editor.Control.Button = Class.create();
Editor.Control.Button.prototype = {
  initialize: function(href, command) {
    this.element = $$("a[href=#" + href + "]").first();
    if (this.element) {
      this.element.id    = href;
      this.element.title = this.element.innerHTML;
  
      this.commandName = href.capitalize().camelize();
      command          = command || new Editor.Command.Base(this.commandName);
  
      Event.observe(this.element, "click", function(event) {
        Event.stop(event);
        command.call();
      });
    }
  }
}

Editor.Control.Menu = Class.create();
Editor.Control.Menu.prototype = {

  baseInitialize: function(button, items) {
    this.selection = false;
    this.button    = new Editor.Control.Button(button, this.toggle.bindAsEventListener(this));
    if (this.button.element) {
      this.root = new Element("div", {"class": "hidden editor_window"});
  
      this.position(this.button.element.up("#editor_toolbar"));
      this.draw(items);
      
      Event.observe(this.root.down("a.close"),
        "click",
        this.toggle.bindAsEventListener(this));
    }
  },

  initialize: function(button, items) {
    this.baseInitialize(button, items);
  },

  position: function(target) {
    target.up("body").appendChild(this.root);
    var pos = Position.cumulativeOffset(target);
    var top = pos[1] + 1;
    var left = pos[0] + target.getWidth() - 1;
    this.root.setStyle({top: top + "px", left: left + "px"});
  },

  toggle: function(event) {
    this.selection = $s();
    this.root.toggleClassName("hidden");
    if (event) { Event.stop(event) }
  },

  draw: function(items) {
    var header = new Element("h1").update('Set Style<a class="close" href="#">close</a>');
    var window_content = new Element("div", {"class": "window_content"});
    var menu_list = new Element("ul", {"class": "editor_menu"});

    $H(items).each((function(pair) {
      var li   = new Element("li");
      var link = new Element("a", {href: "#"}).update(pair.key);
      link.commandTagName = pair.value.tagName;

      li.appendChild(link);
      menu_list.appendChild(li);

      var listener = function(event) {
        Event.stop(event);
        if (this.selection) { this.selection.reset(); } // Help IE return focus to the iframe
        pair.value.call();
        this.toggle();
      }
      Event.observe(link, "click", listener.bindAsEventListener(this));
    }).bind(this));
    this.root.appendChild(header);
    window_content.appendChild(menu_list);
    this.root.appendChild(window_content)
  }
}

Editor.Control.StyleMenu = Class.create();
Object.extend(Object.extend(Editor.Control.StyleMenu.prototype, Editor.Control.Menu.prototype), {

  initialize: function(button, items) {
    this.baseInitialize(button, items);
    if (this.button.element) {
      Event.observe(this.button.element, "click", this.setStyles.bindAsEventListener(this));
    }
  },

  setStyles: function() {
    if (!Editor.current) { return false }

    $A(this.root.getElementsByTagName("a")).each((function(link) {
      var styles  = Editor.current.iframe.computeStylesFor(
        link.commandTagName,
        $w("fontSize fontFamily fontWeight textDecoration color")
      );
      link.setStyle(styles);
    }).bind(this));
  }
});


Editor.Control.Window = Class.create();
Editor.Control.Window.prototype = {

  baseInitialize: function(button) {
    this.selection = false;
    this.button    = new Editor.Control.Button(button, this.toggle.bindAsEventListener(this));
    if (this.button.element) {
      this.root      = new Element("div", { "class": "hidden editor-ui editor_window" });
  
      this.position(this.button.element.up("#editor_toolbar"));
      this.draw();
      
      Event.observe(this.root.down("a.close"),
        "click",
        this.toggle.bindAsEventListener(this));
    }
  },

  initialize: function(button) {
    this.baseInitialize(button);
  },

  position: function(target) {
    target.up("body").appendChild(this.root);
    var pos = target.cumulativeOffset();
    var top = pos[1] + 1;
    var left = pos[0] + target.getWidth() - 1;
    this.root.setStyle({top: top + "px", left: left + "px"});
  },

  toggle: function(event) {
    if (event) { Event.stop(event) }
    if (this.root.hasClassName("hidden")) {
      this.selection = $s();
    }
    this.root.toggleClassName("hidden");
  },
  
  draw: Prototype.emptyFunction
}

Editor.Control.CreateLink = Class.create();
Object.extend(Object.extend(Editor.Control.CreateLink.prototype, Editor.Control.Window.prototype), {

  initialize: function(button, command) {
    this.baseInitialize(button);
    if (this.button.element) {
      this.command = command;
  
      this.getUploadedPhotos("/uploaded_files");
      this.getLivePages("/pages");

			/* OLD - Firefox 3.0 does not like getElementsByClassName
      this.root.getElementsByClassName("editor-create-link-form").each((function(e) {
        Event.observe(e, "submit", this.execute.bindAsEventListener(this));
      }).bind(this));
  		*/
      $$('.editor-create-link-form').each((function(e) {
        Event.observe(e, "submit", this.execute.bindAsEventListener(this));
      }).bind(this));

			/* OLD - Firefox 3.0 does not like getElementsByClassName
      this.root.getElementsByClassName("expander").each(function(e) {
        Event.observe(e, "click", function(event) {
          Event.stop(event);
          if (e.next()) {
            e.toggleClassName("expanded");
            e.next().toggleClassName("hidden");
          }
        });
      });
      */
      $$('.expander').each(function(e) {
        Event.observe(e, "click", function(event) {
          Event.stop(event);
          if (e.next()) {
            e.toggleClassName("expanded");
            e.next().toggleClassName("hidden");
          }
        });
      });
    }
  },

  draw: function() {
    var tpl =' \
      <h1>Add a link<a class="close" href="#">close</a></h1> \
      <div class="window_content">\
        <div class="expander expanded">Click here to link to a page on this website</div> \
        <form action="#" method="post" class="editor-create-link-form"> \
          <label>Link URL</label> \
          <select name="url" size="8" class="live-page-selection"></select> \
          <input type="hidden" name="link_type" value="internal_url" /> \
          <div><input type="submit" value="Add link" /></div> \
        </form> \
        <div class="expander">Click here to link to a page on another website</div> \
        <form action="#" method="post" class="editor-create-link-form hidden"> \
          <label>Link URL</label> \
          <input type="text" name="url" style="width:300px;display:inline;" /> <span>(ex. http:\/\/www.google.com)</span> \
          <input type="hidden" name="link_type" value="external_url" /> \
          <div><input type="submit" value="Add link"/></div> \
        </form> \
        <div class="expander">Click here to link to a file (PDF, Word, etc.) on this website</div> \
        <form action="#" method="post" class="editor-create-link-form hidden"> \
          <label>File</label> \
          <select name="url" size="8" class="uploaded-files-selection"></select> \
          <input type="hidden" name="link_type" value="file" /> \
          <div class="clears"><input type="submit" value="Add link"/></div> \
        </form> \
        <div class="expander">Click here to link to an email address</div> \
        <form action="#" method="post" class="editor-create-link-form hidden"> \
          <label>Email address</label> \
          <input type="text" name="url" style="width:300px;" /> \
          <input type="hidden" name="link_type" value="email" /> \
          <div class="clears"><input type="submit" value="Add link"/></div> \
        </form> \
      </div>';
    this.root.update(tpl);
  },
  
  execute: function(event) {
    Event.stop(event);
    var form      = Event.element(event);
    var url       = form.url.value;
    var link_type = form.link_type.value;
    
    if (this.selection.htmlString != $s().htmlString) this.selection.reset(); // For IE...

    /*
    switch(link_type) {
    case "external_url":
      url = "http://" + url;
      break;
    case "email":
      url = "mailto:" + url;
      break;
    }
    */
    if(link_type == "email") url = "mailto:" + url;

    var text = "";
    this.command.call(url, text);
    if (url) { url = ""; }
    this.toggle();
  },
  
  addUploadedFiles: function(filesJSON) {
    var display = this.root.down(".uploaded-files-selection");
    $A(filesJSON).each((function(hash) {
      var file = new Element("option", {"value": hash.value}).update(hash.text);
      display.appendChild(file);
    }).bind(this));
  },

  getUploadedPhotos: function(url) {
    new Ajax.Request(url, {
      method: "get",
      onSuccess: (function(transport) {
        this.addUploadedFiles(transport.responseText.evalJSON());
      }).bind(this)
    });
  },
  
  addLivePages: function(pagesJSON) {
    var display = this.root.down(".live-page-selection");
    $A(pagesJSON).each((function(hash) {
      custom_class = hash.value == hash.text ? "custom_page" : "";
      var page = new Element("option", {"value": hash.value, "class": custom_class}).update(hash.text);
      display.appendChild(page);
    }).bind(this));
  },

  getLivePages: function(url) {
    new Ajax.Request(url, {
      method: "get",
      onSuccess: (function(transport) {
        this.addLivePages(transport.responseText.evalJSON());
      }).bind(this)
    });
  }
});
  
Editor.Control.InsertImage = Class.create();
Object.extend(Object.extend(Editor.Control.InsertImage.prototype, Editor.Control.Window.prototype), {

  initialize: function(button, command) {
    this.baseInitialize(button);
    this.command = command;
  },

  draw: function() {
    var header = new Element("h1").update('Add an image<a class="close" href="#">close</a>');
    this.root.appendChild(header);
    
    this.picklist = new Element("div", {"class": "picklist"}).update("<h2>Select a gallery</h2><ul></ul>");
    this.display  = new Element("div", {"class": "photo_display"});
    this.picker   = new Element("div", {"class": "editor_image_picker"});
    this.root.appendChild(this.picklist);
    this.root.appendChild(this.display);
    this.root.appendChild(this.picker);

    this.getGalleries("/photo_galleries");
  },
  
  addGalleries: function(galleries) {
    var ul = this.picklist.down("ul");
    $H(galleries).each((function(pair) {
      var li   = new Element("li");
      var link = new Element("a", {href: pair.value}).update(pair.key);
      li.appendChild(link);
      ul.appendChild(li);

      Event.observe(link, "click", (function(event) {
        Event.stop(event);
        var url = Event.element(event).readAttribute("href");
        this.getPhotos(url);
      }).bindAsEventListener(this))
    }).bind(this));
  },
  
  getGalleries: function(url) {
    new Ajax.Request(url, {
      method: "get",
      onSuccess: (function(transport) {
        this.addGalleries(transport.responseText.evalJSON());
      }).bind(this)
    });
  },

  addImages: function(imageJSON) {
    this.display.update("<h2>Select an image</h2>");
    $A(imageJSON).each((function(hash) {
      var image = new Element("img", {alt: hash.caption, src: hash.show});
      this.display.appendChild(image);
      new Editor.Control.ImageDialog(image, hash.versions, this.execute.bind(this));
    }).bind(this));
  },

  getPhotos: function(url) {
    new Ajax.Request(url, {
      method: "get",
      onSuccess: (function(transport) {
        this.addImages(transport.responseText.evalJSON());
        this.picker.update(""); //Clear prior selected photo
      }).bind(this)
    });
  },

  execute: function(src, align) {
    if (this.selection) { this.selection.reset(); }
    this.toggle();
    this.command.call(src, align);
  }
});

Editor.Control.ImageDialog = Class.create();
Editor.Control.ImageDialog.prototype = {

  initialize: function(image, versions, callback) {
    this.callback  = callback;
    this.src       = image.readAttribute("src");
    this.alignment = "block";
    this.image     = image;
    this.versions  = versions;

    image.wrap("div");
    image.wrap(new Element("a", {href: "#"}));

    this.root = $$(".editor_image_picker").first();
    Event.observe(image.up("a"), "click", this.draw.bindAsEventListener(this));
  },

  draw: function(event) {
    if(event) {Event.stop(event)};
    var tpl = new Template(' \
      <h2>Insert the image</h2> \
      <img src="#{href}"/> \
      <p class="versions">Version \
        #{versions} \
      </p> \
      <p class="alignment"> Alignment\
        <a href="#left" class="align_image_left" title="Wrap text to the right of this image"></a> \
        <a href="#right" class="align_image_right" title="Wrap text to the left of this image"></a> \
        <a href="#block" class="align_image_block" title="Do not wrap text around this image"></a> \
      </p> \
      <form action="#" method="post"> \
        <input type="hidden" name="url"/> \
        <input type="hidden" name="alignment"/> \
        <input type="submit" value="Insert image"/> \
      </form>');
    this.root.update(tpl.evaluate({
      href:     this.image.readAttribute("src"),
      versions: this.versionLinks()
    }));

    this.setAlignment();
    this.setVersion();

    Event.observe(this.root.down("form"), "submit", this.onSubmit.bindAsEventListener(this));
    this.root.down(".alignment").immediateDescendants().each((function(link) {
      Event.observe(link, "click", this.setAlignment.bindAsEventListener(this));
    }).bind(this));
    this.root.down(".versions").immediateDescendants().each((function(link) {
      Event.observe(link, "click", this.setVersion.bindAsEventListener(this));
    }).bind(this));
  },

  versionLinks: function() {
    var tpl = new Template('<a class="#{className}" href="#{href}">#{name} <span>(#{width} x #{height})</span></a>');
    return this.versions.map(function(v) {
      return tpl.evaluate(v); 
    }).join("\n");
  },

  setVersion: function(event) {
    if (event) {
      Event.stop(event);
      var current = Event.findElement(event, "a");
    } else {
      var current = this.root.down(".versions a");
    }
    this.src = current.readAttribute("href");
    this.root.down(".versions").immediateDescendants().invoke("removeClassName", "current");
    current.addClassName("current");
  },

  setAlignment: function(event) {
    if (event) {
      Event.stop(event);
      var current = Event.element(event);
    } else {
      var current = this.root.down(".alignment a.align_image_left");
    }
    this.alignment = current.href.replace(/^([^#]+)?#/, "");
    this.root.down(".alignment").immediateDescendants().invoke("removeClassName", "current");
    current.addClassName("current");
  },

  onSubmit: function(event) {
    Event.stop(event);
    this.callback(this.src, this.alignment);
  }
}
