// smMarkerTool - a mousedriven marker tool
// Author - Igor Szyporyn
// Owner - System & Metode A/S
// Requires - jQuery

(function($) {

  var prefix = 'smMarkerTool',
      _methods = {
        addPrefix   : function( name ) {
          return name + '.' + prefix;
        }
      };

  var methods = {

    init      : function( options ) {

      var settings =  $.extend(true, {}, {
                        design            : {
                          borderColor   : '#369',
                          borderWidth   : '1px',
                          borderStyle   : 'solid', 
                          background    : '#def',
                          opacity       : 0.5
                        },
                        modifierKey       : 'altKey',
                        beforeDraw        : $.noop,
                        onDrawBefore      : $.noop,
                        onDrawAfter       : $.noop,
                        afterDraw         : $.noop
                      }, options);

      return this.each(function() {

        var $this = $(this),
            data = $this.data(prefix);

        if (!data) {

          var marker = {
            allowMarking    : false,
            isMarking       : false,
            $element        : $('<div />').css({
                                'border-width'      : settings.design.borderWidth,
                                'border-color'      : settings.design.borderColor,
                                'border-style'      : settings.design.borderStyle,
                                'background-color'  : settings.design.background,
                                'opacity'           : settings.design.opacity,
                                'position'          : 'absolute'
                              }),
            $backdrop       : $('<div />').css({
                                'position'          : 'absolute',
                                'margin'              : '0px',
                                'padding'             : '0px'
                              }),
            dimensions      : [],
            clicked         : {},
            target          : [],
            getDimensions : function() {
              var $el = this.$element, 
                  offset = $el.offset();

              this.dimensions = {
                left    : offset.left,
                top     : offset.top,
                width   : $el.outerWidth(),
                height  : $el.outerHeight()
              };

              return this.dimensions;

            }, 
            setDimensions : function( newDim ) {
                this.dimensions = newDim;
                return this;
            }
          }

          $this.bind( _methods.addPrefix( 'mousedown' ), function( event ) {

            if ( event[settings.modifierKey] ) {

              event.stopPropagation();

              settings.beforeDraw.call( this, marker, event.target );

              marker.clicked = {
                x : event.pageX,
                y : event.pageY
              };

              marker.$backdrop
                .css({
                  'width'   : $('body').outerWidth(true),
                  'height'  : $('body').outerHeight(true),
                  'top'     : '0px',
                  'left'    : '0px',
                  'z-index' : '9998'
                })
                .appendTo($('body'))
                .bind( _methods.addPrefix( 'mousemove' ), function( event ) {
                
                  if ( marker.allowMarking ) {

                    var xD = event.pageX - marker.clicked.x,
                        yD = event.pageY - marker.clicked.y,
                        newDim = {
                          left    : event.pageX < marker.clicked.x ? event.pageX : marker.clicked.x,
                          top     : event.pageY < marker.clicked.y ? event.pageY : marker.clicked.y,
                          width   : event.pageX < marker.clicked.x ? xD * -1 : xD,
                          height  : event.pageY < marker.clicked.y ? yD * -1 : yD
                        };

                    settings.onDrawBefore.call( this, marker, newDim );

                    marker.$element.css({
                      'left'    : newDim.left + 'px',
                      'top'     : newDim.top + 'px',
                      'width'   : newDim.width + 'px',
                      'height'  : newDim.height + 'px'
                    });
                    
                    marker.setDimensions( newDim );

                    settings.onDrawAfter.call( this, marker, newDim );

                  }  
                  
                })        
                .bind( _methods.addPrefix( 'mouseup' ), function( event ) {
                
                  if ( marker.isMarking === true ) {
                    marker.$element.remove();
                    marker.$backdrop.remove();
                    marker.allowMarking = false;
                    marker.isMarking = false;
                    settings.afterDraw.call( this, marker );
                  }
                  
                });

              marker.$element
                .css({
                  'width'   : '0px',
                  'height'  : '0px',
                  'top'     : marker.clicked.y,
                  'left'    : marker.clicked.x,
                  'z-index' : '9999'
                })
                .appendTo(marker.$backdrop);

              marker.element = marker.$element.get(0);
              marker.target = event.target;
              marker.allowMarking = true;
              marker.isMarking = true;

            }

          });
          /*
          $this.bind( _methods.addPrefix( 'mousemove' ), function( event ) {
          
            if ( marker.allowMarking ) {

              var xD = event.pageX - marker.clicked.x,
                  yD = event.pageY - marker.clicked.y,
                  newDim = {
                    left    : event.pageX < marker.clicked.x ? event.pageX : marker.clicked.x,
                    top     : event.pageY < marker.clicked.y ? event.pageY : marker.clicked.y,
                    width   : event.pageX < marker.clicked.x ? xD * -1 : xD,
                    height  : event.pageY < marker.clicked.y ? yD * -1 : yD
                  };

              settings.onDrawBefore.call( this, marker, newDim );

              marker.$element.css({
                'left'    : newDim.left + 'px',
                'top'     : newDim.top + 'px',
                'width'   : newDim.width + 'px',
                'height'  : newDim.height + 'px'
              });
              
              marker.setDimensions( newDim );

              settings.onDrawAfter.call( this, marker, newDim );

            }  
            
          });
          
          $this.bind( _methods.addPrefix( 'mouseup' ), function( event ) {
          
            if ( marker.isMarking === true ) {
              marker.$element.remove();
              marker.$backdrop.remove();
              marker.allowMarking = false;
              marker.isMarking = false;
              settings.afterDraw.call( this, marker );
            }
            
          });
          */

        }

        $this.data( prefix, true );

      });

    },
    destroy   : function() {

      //this.unbind( _methods.addPrefix( 'mousedown' ) ).unbind( _methods.addPrefix( 'mousemove' ) ).unbind( _methods.addPrefix( 'mouseup' ) );
      
      this.unbind( _methods.addPrefix( 'mousedown' ) );
      
      this.data( prefix, false );

      return this;

    } 
  }

  $.fn[prefix] = function( method ) {

    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.' + prefix );
    }

  }



})(jQuery);