(function($) {

/**
 * Allows drag'n'drop placement of Imagefield/Imagecache images into nodes.
 */

  $.imageplacement = {

    init: function(options) {
      if (!Drupal.jsEnabled) return false;

      // Check for imagefields before anything else
      var $fields = Drupal.settings.imageplacement_fieldspos;
      if ($fields == undefined) return false;

      // Make sure settings are defined
      var $settings = Drupal.settings.imageplacement;
      if ($settings == undefined) return false;

      var settings = {
        'enable': $settings.enable,
        'callback': $settings.callback,
        'saveurl': $settings.saveurl
      };

      if (options) $.extend(settings, options);

      // Killswitch
      if (!settings.enable) return false;
      if (settings.saveurl == undefined) return false;

      var $clear = $('<div class="imageplacement_clear">&nbsp;</div>');

      $.each($fields, function() {
        var field = this;

        if (this.teaser == 'true') {
          var node_selector = '-teaser';
          var field_selector = ':first';
        }
        else {
          var node_selector = '';
          var field_selector = ':last';
        }

        var fields_selector = '#node-' + this.nid + node_selector + ' .' + this.field + field_selector;
        var $field_elements = $(fields_selector);

        if ($($field_elements).length > 0) {
          $field_elements.each( function(i) {
            var $field = $(this);
            var $content = $field.parent();
            var $contentps = $content.find('p');
            $content.append($clear);

            $field.draggable({
              containment: $content,
              refreshPositions: true,
              helper: 'clone',
              opacity: 0.7,
              start: function(e, ui) {
                // We set an adjusted width after depending on the floated field's width
                halfwidth = (($content.width() / 2) - ($field.width() / 2));
                halfheight = (($content.height() / 2) - ($field.width() / 2));
              },
              drag: function(e,ui) {
                // Make calculations if we apply left or right floats and where
                // we will be inserting the image in the text here
                $.imageplacement.checkPos('drag', $(this), $content, field, ui.position.left, halfwidth, ui.position.top, halfheight);
              },
              stop: function(e,ui) {
                // We set an adjusted width after depending on the floated field's width
                halfwidth = (($content.width() / 2) - ($field.width() / 2));
                halfheight = (($content.height() / 2) - ($field.width() / 2));

                // Confirm position and save
                var $pos = $.imageplacement.checkPos('stop', $(this), $content, field, ui.position.left, halfwidth, ui.position.top, halfheight);
                $pos.field = field.field;
                $pos.teaser = field.teaser;
                $pos.numps = $contentps.length;
                $pos.whichp = field.whichp;
                $pos.pcontent = (field.pcontent) ? field.pcontent : '';
  
                var pb = new Drupal.progressBar('imageplacement-saving');
                var $pb = $(pb.element);
                $content.prepend($pb);
                $('#imageplacement-messages').remove();
                $.post(settings.saveurl, $pos, function(data) {
                  var $msg = $('<div id="imageplacement-messages"></div>').html(data);
                  $content.prepend($clear).prepend($msg);
                  $('#imageplacement-saving').remove();
                  setTimeout( function() {
                    $msg.animate({
                      height: 0,
                      marginTop: 0,
                      marginBottom: 0,
                      paddingTop: 0,
                      paddingBottom: 0,
                      opacity: 0
                    }, 'slow', 'linear', function() {
                      $(this).remove();
                    });
                  }, 5000);
                });
              }
            });

            // <p> support
            $contentps.each( function(i) {
              $(this).droppable({
                accept: fields_selector,
                hoverClass: 'imageplacement_p_hover',
                tolerance: 'pointer',
                over: function(e, ui) {
                  $(this).before($field);
/*                   $field.draggable('option', 'containment', $(this)); */
                },
                out: function(e, ui) {
                  $content.append($field);
                  field.pcontent = '';
/*                   $field.draggable('option', 'containment', $content); */
                },
                drop: function(e, ui) {
                  field.whichp = i;
                  field.pcontent = $(this).text().substr(0,255);
                }
              });
            });

          });
        }
      });

      return $fields;
    },

    checkPos: function(op, $field, $content, field, left, hw, top, hh) {
      $pos = {};

      if (left <= hw) {
        $field.addClass('imageplacement_left').removeClass('imageplacement_right'); // try toggleClass just for fun :p
        $pos.left = 'left';
      }
      else {
        $field.addClass('imageplacement_right').removeClass('imageplacement_left');
        $pos.left = 'right';
      }
      if (top <= hh) {
        if (op == 'stop') $content.prepend($field);
        $field.addClass('imageplacement_top').removeClass('imageplacement_bottom');
        $pos.top = 'top';
      }
      else {
        if (op == 'stop') $content.find('.clear:last').before($field);
        $field.addClass('imageplacement_bottom').removeClass('imageplacement_top');
        $pos.top = 'bottom';
      }
      if (field.numps && field.pcontent && op == 'stop') {
        $content.find('p:eq('+field.whichp+')').before($field);
      }
      return $pos;
    },
    
    placeImages: function() {
      var $clear = $('<div class="imageplacement_clear">&nbsp;</div>');
      var $fields = Drupal.settings.imageplacement_fieldspos;

      $.each($fields, function(i) {
        if (this.teaser == 'true') {
          var node_selector = '-teaser';
          var field_selector = ':first';
        }
        else {
          var node_selector = '';
          var field_selector = ':last';
        }

        var fields_selector = '#node-' + this.nid + node_selector + ' .' + this.field + field_selector;
        var $field_elements = $(fields_selector);

        if ($field_elements.length > 0) {
          $field_elements.each( function() {
            var $field = $(this);
            var $content = $field.parent();
            var $contentps = $content.find('p');

            $content.append($clear);

            if ($fields[i].left == 'left') {
                $field.addClass('imageplacement_left');
            }
            else if ($fields[i].left == 'right') {
                $field.addClass('imageplacement_right');
            }
            if ($fields[i].numps && $fields[i].pcontent) {
              if ($contentps.length == $fields[i].numps) {
                $content.find('p:eq('+$fields[i].whichp+')').before($field);
              }
              else { // The amount of <p> tags changed, find our paragraph with the levenshtein function
                var plevs = [];
                $contentps.each( function() {
                  plevs.push($.imageplacement.levenshtein($(this).text().substr(0,255), $fields[i].pcontent));
                });
                var bestp = $.imageplacement.min(plevs);
                for (i in plevs) {
                  if (plevs[i] == bestp) {
                    $content.find('p:eq('+i+')').before($field);
                  }
                }
              }
            }
            else if ($fields[i].top == 'top') {
                $content.prepend($field);
                $field.addClass('imageplacement_top');
            }
            else if ($fields[i].top == 'bottom') {
                $content.find('.imageplacement_clear:last').before($field);
                $field.addClass('imageplacement_bottom');
            }
          });
        }

      });
    },
    
    levenshtein: function (a, b) {
        // http://kevin.vanzonneveld.net
        // +      original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com)
        // +      bugfixed by: Onno Marsman
        // +       revised by: Andrea Giammarchi (http://webreflection.blogspot.com)
        // + reimplemented by: Brett Zamir (http://brettz9.blogspot.com)
        // *        example 1: levenshtein('Kevin van Zonneveld', 'Kevin van Sommeveld');
        // *        returns 1: 3
        
        var min=Math.min, len1=0, len2=0, I=0, i=0, d=[], c='', j=0, J=0;
     
        // BEGIN STATIC
        var split = false;
        try{
            split=!('0')[0];
        } catch(e){
            split=true; // Earlier IE may not support access by string index
        }
        // END STATIC
        
        if (a == b) {
            return 0;
        }
        if (!a.length || !b.length) {
            return b.length || a.length;
        }
        if (split){
            a = a.split('');b = b.split('');
        }
        len1 = a.length + 1;
        len2 = b.length + 1;
        d = [[0]];
        while (++i < len2) {
            d[0][i] = i;
        }
        i = 0;
        while (++i < len1) {
            J = j = 0;
            c = a[I];
            d[i] = [i];
            while (++j < len2) {
                d[i][j] = min(d[I][j] + 1, d[i][J] + 1, d[I][J] + (c != b[J]));
                ++J;
            }
            ++I;
        }
        
        return d[len1 - 1][len2 - 1];
    },

    // http://ejohn.org/blog/fast-javascript-maxmin/    
    min: function( array ){
      return Math.min.apply( Math, array );
    }
  
  };

  Drupal.behaviors.imageplacement = function() {
    $.imageplacement.init();
  }

})(jQuery);
