var Presenter = Class.create({
  initialize: function(options) {
    this.buildBackground();
    options   = $H(options);
    this.root = $(options.get("root")) || this.buildRoot();
    $(options.get("parent") || Element.body()).insert(this.root);
  },

  buildBackground: function() {
    this.background = new Element("div").setStyle({
      position:        "absolute",
      width:           "100%",
      height:          "100%",
      top:             "0",
      left:            "0",
      opacity:         0.85,
      backgroundColor: "#fff"
    });
    this.background.observe("click", this.close.bindAsEventListener(this));
    Element.body().insert(this.background);
  },

  buildRoot: function() {
    return new Element("div", {"id": "image_picker_background"}).setStyle({
      position:        "absolute",
      width:           "80%",
      height:          "80%",
      top:             "10%",
      left:            "10%",
      opacity:         1.0
    });
  },

  open: function(event, bubble) {
    if (event && !bubble) { event.stop() }
    this.background.show();
    this.root.show();
  },

  close: function(event, bubble) {
    if (event && !bubble) { event.stop() }
    this.root.hide();
    this.background.hide();
  },

  update: function(element_or_html_text) {
    this.root.update(element_or_html_text);
  }
});


var UploadedImage = Class.create({
  initialize: function(element) {
    this.element = $(element);
    this.image   = this.element.down("img");
    this.name    = this.element.down(".name").innerHTML.strip();
    this.size    = "medium";

    this.addSizeLinks();

    this.element.observe("mousedown", this.select.bindAsEventListener(this));
  },

  url: function() {
    if (!this._url) {
      this._url = this.image.readAttribute("src").gsub(/\?\d+$/, "").split(/_tiny/);
    }
    return this._url[0] + "_" + this.size + this._url[1];
  },

  description: function() {
    if (!this._description) {
      this._description = this.image.readAttribute("alt");
    }
    return this._description == "" ? this.name : this._description;
  },

  select: function(event) {
    event.stop();
    this.markSelected();
    (this.onSelect || Prototype.K).call(this);
  },

  submit: function(event) {
    event.stop();
    this.size = event.element().readAttribute("href").gsub(/.*#/, "");
    (this.onSubmit || Prototype.K).call(this);
  },

  markSelected: function() {
    this.element.siblings().each(function(e) {
      e.removeClassName("selected");
      e.down("ul").hide();
    });
    this.element.down("ul").show();
    this.element.addClassName("selected");
  },

  addSizeLinks: function() {
    var list  = this.buildSizeList();
    var links = $w("tiny small medium large x_large").map(function(size) {
      return new Element("a", { href: "#" + size }).update(size == "x_large" ? "Extra large" : size.capitalize());
    });

    var callback = (function(event) {
      list.hide();
      this.submit(event);
    }).bindAsEventListener(this);

    links.each(function(link) {
      link.observe("click", callback);
      list.insert(new Element("li").update(link));
    });

    this.element.insert(list);
  },

  buildSizeList: function() {
    var l = new Element("ul", { "class": "image_size_selector" });
    var dim = this.element.getDimensions();
    var pos = this.element.positionedOffset();
    l.setStyle({
      position: "absolute",
      width:    (dim.width - 2) + "px",
      top:      (dim.height + pos.top) + "px",
      left:     pos.left + "px"
    });
    l.hide();
    return l;
  }
});


var ImageGalleriesPresenter = Class.create(Presenter, {
  show_window: function(element_or_html_text) {
    this.root.update(element_or_html_text);
    this.extendUploadedImages();

    var iterator = function(link) {
      link.makeRemote(this, {
        onSuccess: (function(xhr) {
          this.reset_gallery_links();
          link.addClassName("selected");
          this.show_gallery(xhr.responseText);
        }).bind(this)
      });
    }
    $("image_picker").select("ul a").each(iterator.bind(this));
    $("image_picker").setStyle({opacity: 1.0});
    this.form().observe("submit", this.capture_submit.bindAsEventListener(this));

    var close_callback = function(event) {
      event.stop();
      this.reset_and_close();
    }
    $("image_picker").down("a.close").observe("click", close_callback.bindAsEventListener(this));

    var align_links = $("image_picker_align_image").select("a");
    var align_link_callback = (function(event) {
      event.stop();
      var element      = event.element().nodeName == "A" ? event.element() : event.element().up("a");
      var new_value    = element.readAttribute("href").gsub(/^(.)*#align_/, "");
      $("align").value = new_value;
      this.reset_align_links(new_value);
    }).bindAsEventListener(this);
    align_links.each(function(link) { link.observe("click", align_link_callback) });
    this.reset_align_links(this.form("align"));

    var h = this.root.getHeight() - this.form().getHeight() - 2;
    $("image_picker_gallery_list").setStyle({ "height": h + "px" });
  },

  show_gallery: function(element_or_html_text) {
    $("image_picker_image_list").update(element_or_html_text);
    this.extendUploadedImages();
  },

  extendUploadedImages: function() {
    $$(".uploaded_image").each(function(div) {
      var i = new UploadedImage(div);
      i.onSubmit = function() {
        $("url").value = i.url();
        $("alt").value = i.description();
      }
    });
  },

  reset_and_close: function() {
    this.close();
    this.reset_align_links();
    this.form()["url"].clear(); this.form()["alt"].clear();
  },

  reset_align_links: function(new_value) {
    new_value = new_value || "block";
    $("image_picker_align_image").select("a").each(function(l) { l.removeClassName("selected") });
    $$("#image_picker_align_image a[href$=#align_" + new_value + "]").first().addClassName("selected");
  },

  reset_gallery_links: function() {
    $("image_picker_gallery_list").select("a").each(function(l) { l.removeClassName("selected") });
  },

  capture_submit: function(event) {
    event.stop();
    (this.onSubmit || Prototype.K).call(this, 
      this.form("url"),
      this.form("alt"),
      "image_" + this.form("align")
    );
    this.reset_and_close();
  },

  form: function(element) {
    var f = $("image_picker").down("form");
    if (element) {
      return $F(f[element]);
    } else {
      return f;
    }
  }
});


var ImageGalleriesPlugin = Class.create({
  activate: function(editor) {
    this.buildPresenter();
    this.presenter.open();
    this.editor = editor;
    new Ajax.Request("/admin/image_galleries", {
      method: "get",
      parameters: this.buildRequestParams(),
      onSuccess: (function(xhr) {
        this.presenter.show_window(xhr.responseText);
      }).bind(this)
    });
  },

  buildPresenter: function() {
    if (this.presenter) { return }
    this.presenter = new ImageGalleriesPresenter();
    this.presenter.onSubmit = this.insertImage.bind(this);
  },

  buildRequestParams: function() {
    var url = "", alt = "", align = "", element = this.editor.selection.getNode();
    if (this.editor.selection.getNode().nodeName == "IMG") {
      url   = this.editor.dom.getAttrib(element, "src");
      alt   = this.editor.dom.getAttrib(element, "alt");
      align = this.editor.dom.getAttrib(element, "class").gsub(/image_/, "");
    }
    return {
      image_url: url,
      image_alt: alt,
      image_align: $w("right left center").include(align) ? align : "block"
    }
  },

  insertImage: function(url, description, class_names) {
    this.editor.execCommand('mceInsertContent', false, this.editor.dom.createHTML("img", {
      src: url,
      alt: description,
      "class": class_names
    }));
  }
});
