// Puzzle.js
// A simple puzzle game using MooTools and Moo.FX for Web Scripting Power Tools.
// Erik Kastner 2007-02-05

Array.extend({
  swap: function(i,j) {
    ti = this[i];
    this[i] = this[j];
    this[j] = ti;
  },
  
  randomize: function() {
    newArray = [];
    var i = this.length;
    while (--i) {
      var j = $random(0,i);
      this.swap(i,j); 
    }
    return this;
  },
  
  inGroupsOf: function(number, fn, bind) {
    lastI = 0;
    for(var i=number; i<=this.length; i+=number) {
      fn.call(bind, this.slice(lastI, i), this)
      lastI = i;
    }
    return true;
  }

});

Puzzle = new Class({
  
  rows: 4,
  cols: 5,
  
  initialize: function(image) {
    this.image = image;
    this.width = image.width;
    this.height = image.height;
    if (image.height > image.width) {
      var orows = this.rows;
      this.rows = this.cols;
      this.cols = orows;
    }
    if (image.height == image.width) this.rows = this.cols;
    this.boxHeight = parseInt(this.height / this.rows);
    this.boxWidth = parseInt(this.width / this.cols);
    this.top = image.getTop();
    this.left = image.getLeft();
    this.src = image.src;
    this.coOrds = [];
    this.moving = {};
    this.wrap = new Element("div").setStyles({
      position: "absolute",
      top: this.top + "px",
      left: this.left + "px",
      width: this.width + "px",
      height: this.height + "px",
      padding: 0
    }).injectInside(document.body);
    image.setStyle('position', 'absolute')
    image.setOpacity(0)
    this.makeSubBoxes();
    this.makeButton();
  },
  
  
  makeSubBoxes: function() {
    for(var y=0; y<this.rows; y++) {
      for(var x=0; x<this.cols; x++) {
        var top   = y * this.boxHeight + "px";
        var left  = x * this.boxWidth + "px";
        var box = new Element("div").setStyles({
          top: top,
          left: left,
          position: "absolute",
          width: this.boxWidth + "px",
          height: this.boxHeight + "px",
          background: "white",
          backgroundImage: "url(" + this.src + ")",
          backgroundPosition: ["-", x * this.boxWidth, "px ", "-", y * this.boxHeight, "px"].join("")
        }).setProperty("id", "box_"+top.toInt()+"_"+left.toInt()).injectInside(this.wrap);
        this.coOrds.push({'top': top, 'left': left, 'box': box})
        box.makeDraggable({
          onStart: function(e) {
            e.setStyle('z-index', 1001)
            x = {top: e.getStyle('top'), left: e.getStyle('left'), box: e}
            this.moving = x
          }.bind(this),
          onComplete: function(e) {this.checkBox(e); e.setStyle('z-index', 1000)}.bind(this)
        })
      }
    }
  },
  
  checkBox: function(box) {
    var top = box.getStyle('top');
    var left = box.getStyle('left');
    var hitBox = {box:""};
    
    /*box.blur() */
    this.coOrds.each(function(coOrd){
      var distanceTop = Math.abs(coOrd.top.toInt() - top.toInt());
      var distanceLeft = Math.abs(coOrd.left.toInt() - left.toInt());
      if(distanceTop < (this.boxHeight / 2) && distanceLeft < (this.boxWidth / 2)) {
        hitBox = coOrd;
      }
    },this)
    
    var retAr = this.coOrds.filter(function(coOrd, i) {
      return (coOrd.box == this.moving.box || coOrd.box == hitBox.box)
    }, this)
    
    if (retAr.length == 2) this.swap(retAr[0], retAr[1])
    this.moveBoxes();    
    
  },
  
  makeButton: function() {
    var scrambleButton = new Element("input").setProperties({value: "Igraj!", type: "button"})
    scrambleButton.setStyles({
      position: "absolute",
      left: this.image.getLeft() + 230 + "px"
    })
    
    scrambleButton.addEvent('click', function() {
      this.scramble()
    }.bind(this)).injectInside(document.body)
    
    scrambleButton.effect('margin-top').start(this.height + 15)
    
  },
  
  moveBox: function(boxPlus) {
    boxPlus.box.setStyle('z-index', 1001)
    var trans = boxPlus.transition || Fx.Transitions.backOut
    var fx = new Fx.Styles(boxPlus.box, {
      duration: 800,
      transition: trans,
      onComplete: function(el) { el.setStyle('z-index', 1000) }
    })
    fx.start.delay(this.timer, fx, {'top': boxPlus.top, 'left': boxPlus.left})
  },
  
  swap: function(box1, box2) {
    var bbox = box1.box
    box1.box = box2.box
    box2.box = bbox
  },
  
  moveBoxes: function() {
    this.coOrds.each(function(coOrd) {
      if (coOrd.box.getStyle('top') != coOrd.top || coOrd.box.getStyle('left') != coOrd.left) {
        this.moveBox(coOrd)
        this.timer += 100;
      }
    }, this)
    
    var solved = true;    
    this.coOrds.each(function(coOrd) {
      var sId = coOrd.box.id.split(/_/)
      if (coOrd.top.toInt() != sId[1] || coOrd.left.toInt() != sId[2]) solved = false;
    },this)
    
    if (solved) { this.youWon() }
  },
  
  scramble: function() {
    this.coOrds.randomize()
    this.coOrds.inGroupsOf(2, function(ar) {
      this.swap(ar[0], ar[1])
    }, this)
    this.moveBoxes();
  },

});

window.addEvent('domready', function() {
  $$(".puzzle").each(function(image) { 
/*    image.newEvent("load", function() { new Puzzle(image) })*/
    image.addEvent("load", function() { new Puzzle(image) })
  })
});