var Controls = {};

if (typeof(Draggable) != 'undefined') {
  Controls.Draggable = Behavior.create({
    initialize: function(options) {
      this.options = options;
      new Draggable(this.element, this.options);
    }
  });
  
  Controls.Droppable = Behavior.create({
    initialize : function(options) {
      this.options = options;
      Droppables.add(this.element, this.options);
    }
  });
}

if (typeof(Ajax) != 'undefined' && Ajax.InPlaceEditor) {
  Controls.InPlaceEditor = Behavior.create({
    initialize: function(options) {
      this.options = Object.clone(options);
      if (this.options.externalControl) {
        try {
          var result = eval(this.options.externalControl);
          this.options.externalControl = result;
        } catch (e) {
          console.log(e);
        }
      }
      if (!this.options.callback && window.authenticity_token) {
        this.options.callback = function(form) {
          return Form.serialize(form) + '&authenticity_token=' + encodeURIComponent(window.authenticity_token);
        }
      }
      new Ajax.InPlaceEditor(this.element, this.element.href, this.options);
    }
  });
}

Controls.ImgZoom = Behavior.create({
  initialize: function(options) {
    this.options = Object.extend({
        containerStyle: {},
        active: false,
        onDemand: true,
        remove_from_src: '_[^_]+',
        afterClick: Prototype.K
    }, options || {});
    this.options.image = $(this.options.image);
    this.options.image.setStyle({float: 'left'});
    this.options.image.zoomControl = this;
    this.create();
  },
  reset: function() {
    this.destroy();
    this.create();
  },
  destroy: function() {
    if (this.zoomContainer) {
      this.zoomContainer.remove();
      this.zoomContainer = null;
    }
    if (this.tintAndDrag) {
      this.tintAndDrag.remove();
      this.tintAndDrag = null;
    }
  },
  create: function() {
    var src = this.getFullImgSrc();
    if (src) {
      this.zoomImg = new Element('img', {'src': src});
      this.zoomImg.relativize();

      this.zoomContainer = this.zoomImg.wrap('div', {'class': 'zoomContainer'});
      this.zoomContainer.makeClipping();
      this.zoomContainer.hide();

      this.options.image.insert({after: this.zoomContainer});
      new PeriodicalExecuter(this.calcFactorAndMax.bind(this), 0.5);
    }
  },
  getFullImgSrc: function() {
    var img = this.options.image;
    var src = img.src;
    if (img.style.filter) src = img.style.filter.match(/.*src="([^"]+)"/)[1];
    var matches = src.match("^(.*)" + this.options.remove_from_src + "(\\..*)$");
    return matches ? matches[1]+matches[2] : null;
  },

  calcFactorAndMax: function(periodical) {
    if (!this.options.image.width || !this.zoomImg.width) return;
    periodical.stop();

    if (!parseInt(this.zoomContainer.getStyle('width'))) {
      this.zoomContainer.setStyle({width: this.options.containerStyle.width || this.options.image.width + 'px'});
    }
    if (!parseInt(this.zoomContainer.getStyle('height'))) {
      this.zoomContainer.setStyle({height: this.options.containerStyle.height || this.options.image.height + 'px'});
    }

    var containerDimensions = this.zoomContainer.getDimensions();
    this.cellDimensions = {};
    this.imgMaximum = {};
    this.factor = {};
    this.maximum = {};
    var params = {left: 'width', top: 'height'};
    for (var key in params) {
      var param = params[key];
      this.cellDimensions[param] = Math.min(this.options.image[param], this.options.image[param] * containerDimensions[param] / this.zoomImg[param]);
      this.imgMaximum[key] = Math.max(0, this.options.image[param] - this.cellDimensions[param]);
      this.factor[key] = this.zoomImg[param] / this.options.image[param];
      this.maximum[key] = Math.max(0, this.zoomImg[param] - containerDimensions[param]);
    }

    this.image = this.options.image.cloneNode(false);
    this.image.id = null;
    this.options.image.insert({after: this.image});
    var dimensions = {width: this.image.width+'px', height: this.image.height+'px'};

    this.tintAndDrag = this.image.wrap('div').absolutize().clonePosition(this.options.image).setStyle(dimensions);
    this.tintAndDrag.observe('mouseover', this.show.bindAsEventListener(this));
    this.tintAndDrag.observe('mouseout', this.hide.bindAsEventListener(this));
    this.tintAndDrag.observe('mousemove', this.drag.bindAsEventListener(this));

    this.tint = new Element('div', {'class': 'tint'});
    this.tint.setOpacity(0);
    this.tintAndDrag.insert({top: this.tint});
    this.tint.absolutize().clonePosition(this.options.image);

    this.dragBox = this.image.wrap('div', {'class': 'dragBox'}).absolutize().setStyle({
      width: parseInt(this.cellDimensions.width)+'px',
      height: parseInt(this.cellDimensions.height)+'px',
      overflow: 'hidden',
      visibility: 'hidden'
    });
    this.image.absolutize();
    if (this.options.onDemand && !this.options.active) this.tintAndDrag.hide();
  },

  onclick: function(e) {
    e.stop();
    this.tintAndDrag.toggle();
    this.options.active = !this.options.active;
    this.options.clickCallback(this.element);
  },
  show: function(event) {
    if (this.options.onDemand && !this.options.active) return;
    this.zoomContainer.show();
    this.tint.setOpacity(0.5);
    this.dragBox.setStyle({visibility: 'visible'});
  },
  hide: function(event) {
    if (this.options.onDemand && !this.options.active) return;
    this.zoomContainer.hide();
    this.tint.setOpacity(0);
    this.dragBox.setStyle({visibility: 'hidden'});
  },
  drag: function(event) {
    var offset = this.image.cumulativeOffset();
    var position = {
      left: Math.max(0, event.pointerX() - offset.left - this.cellDimensions.width/2),
      top: Math.max(0, event.pointerY() - offset.top - this.cellDimensions.height/2)
    };

    var imgPosition = Object.clone(position);
    for(var dir in imgPosition) {
      imgPosition[dir] = Math.min(imgPosition[dir], this.imgMaximum[dir]) + "px";
    }
    this.dragBox.setStyle(imgPosition);
    for(var dir in imgPosition) {
      imgPosition[dir] = "-" + imgPosition[dir];
    }
    this.image.setStyle(imgPosition);

    for (var dir in position) {
      position[dir] = (-Math.min(position[dir] * this.factor[dir], this.maximum[dir])) + "px";
    }
    this.zoomImg.setStyle(position);
  }
});

Remote.Links = Behavior.create(Remote.Link, {
  initialize : function($super, options) {
    $super(options);
    this.options.tagName = this.options.tagName || 'a';
  },
  onclick : function(e) {
    var element = e.element();
    if (!element.match(this.options.tagName)) element = element.up(this.options.tagName);
    if (!element) return true;
    
    var options = Object.extend({ url : element.href, method : 'get' }, this.options);
    return this._makeRequest(options);
  }
});

Controls.ChangeImage = Behavior.create({
  initialize : function(options) {
    // replace_src must be an object with attributes from and to, from string will be replaced in src with to string
    // if replace_src is false, loads href
    this.options = Object.extend({
      big_image: 'card_image',
      replace_src: null,
      tagName: 'a'
    }, options);
  },
  onclick : function(e) {
    var element = e.element();
    if (!element.match(this.options.tagName)) element = element.up(this.options.tagName);
    if (!element) return true;
    
    Controls.ChangeImage.load_image(this.options.big_image, this.get_src_to_load(element), this.get_alt(element));
    if (this.options.callback) this.options.callback.apply(this, [element]);
    return false;
  },
  get_src_to_load : function(element) {
    if (this.options.replace_src) {
      return element.down('img').src.replace(this.options.replace_src.from, this.options.replace_src.to);
    } else return element.href;
  },
  get_alt : function(element) {
    var img = element.down('img');
    return img ? img.alt : '';
  }
});
Controls.ChangeImage.load_image = function(big_image, src, alt, zoom) {
    if (Object.isUndefined(zoom)) zoom = true; // default is true
    var img = $(big_image);
    if (img.style.filter) img.style.filter = ''; // for IE6
    img.src = src;
    img.alt = alt;
    if (img.zoomControl) {
      if (zoom) {
        img.zoomControl.reset();
        Element.show('zoomControls');
      } else {
        img.zoomControl.destroy();
        Element.hide('zoomControls');
      }
    }
}
