/*
  Diese Datei "puzzle.js" ist Bestandteil des Projektes
  "puzzle-Objekte" und demonstriert Moeglichkeiten der
  objektorientierten Programmierung einer Drag-and-Drop-Anwendung
  unter JavaScript.

  In dieser Datei befinden sich alle Eigenschaften und Methoden,
  um die puzzlekarten mit den noetigen Funktionen zu versehen.

   ----- Autor: Stefan Spohn, April 2001 -------
*/

var globDrag = false;
// flag for drag and drop
// this var must be set here because otherwise MS Explorer
// will throw an error if puzzle is startet from desktop by double click

function oPuzz(x, y, imgName, id)
{
  /*
    each card object automatically creates its start field as embedded object
  */
  this.startPos = new oSquare(x, y, borderImage);

  // inheritance:
  // oSquare is parent class of oPuzz
  // 'basedOn' is arbitrary
  this.basedOn = oSquare;

  // start constructor of parent class
  this.basedOn(x, y, imgName, id);

  // properties
  this.id        = id;
  this.ImgID     = document.images.length - 1; // for opera;
  this.zIndex    = globIndex;
  this.el        = GetRef("puzz" + id);

  // methods
  this.chgPic    = mPuzz_chgPic;
  this.moveBy    = mPuzz_moveBy;
  this.moveTo    = mPuzz_moveTo;
  this.move      = mPuzz_move;
  this.toStart   = mPuzz_toStart;
  this.chgWith   = mPuzz_chgWith;
  this.setIndex  = mPuzz_setIndex;
  this.intersect = mPuzz_intersect;

  // event handler for each card
  if (this.el.captureEvents) // for NC 4
    this.el.captureEvents(Event.MOUSEDOWN);

  this.el.onmousedown = mdown; // for NC4 and other browsers
}

// event handler of document
if (document.captureEvents)
  document.captureEvents(Event.MOUSEMOVE | Event.MOUSEUP);

document.onmousemove = mmove;
document.onmouseup = mup;




function mdown(e)
{
  // mouse down
  clickX = getX(e);
  clickY = getY(e);

  // check which card has been clicked
  var i = 0;
  while (puzz[i++].el != this){};

  clickedPuzz = puzz[--i];
  clickedPuzz.setIndex(++globIndex);

  globDrag = true;

  return false;
}

function mmove(e)
{
  // mouse movement
  if (!globDrag) return;

  var newX = getX(e);
  var newY = getY(e);

  var distX = (newX - clickX);
  var distY = (newY - clickY);

  // save mouse position
  clickX = newX;
  clickY = newY;

  clickedPuzz.moveBy(distX, distY);
}

function mup(e)
{
  // mouse up
  var i     = countCards;
  var max   = 0;
  var field = -1;
  var n;

  globDrag = false;
  if (!clickedPuzz)
    return;

  // check which which gamefield has the biggest intersection with dropped card
  while(i--)
  {
    n = clickedPuzz.intersect(gameField[i]);
    if (n > max)
    {
      max   = n;
      field = i;
    }
  }

  // card is put on the gamefield with the biggest intersection
  if (field > - 1) {
    clickedPuzz.moveTo(gameField[field].x, gameField[field].y);
    // HBX and IVW
    countPixel(); 
  }

  puzzleSolved();
  clickedPuzz = null;
}

function oSquare(x, y, img, id)
{
  this.x   = x;
  this.y   = y;
  this.img = pathToImgs + img;

  createLayer(x, y, img, id);
}

function mPuzz_moveBy(distX, distY)
{
  this.x += distX;
  this.y += distY;

  this.move();
}

function mPuzz_moveTo(ToX, ToY)
{
  this.x = ToX;
  this.y = ToY;

  this.move();
}

function mPuzz_move()
/*
  set new position of object
*/
{
  if (isNC4())
    this.el.moveTo(this.x, this.y);

  if(isMSIE() || isMoz() || isOpera())
  {
    this.el.style.left = this.x + "px";
    this.el.style.top  = this.y + "px";
  }
}

function mPuzz_chgWith(chgObj)
{
  var tempX, tempY;
  tempX = this.x;
  tempY = this.y;

  // put cards above startfields
  this.setIndex(++globIndex);
  this.moveTo(chgObj.x, chgObj.y);
  chgObj.moveTo(tempX, tempY);

  var t = this.startPos;
  this.startPos = chgObj.startPos;
  chgObj.startPos = t;
}

function mPuzz_intersect(obj)
/*
  check which gamefield has the biggest intersection with card
*/
{
  var diffX;

  if (this.x < obj.x)
    diffX = this.x + imageWidth - obj.x
  else
    diffX = obj.x + imageWidth - this.x


  if (diffX < 0 || diffX > imageWidth)
   diffX = 0;

  if (this.y < obj.y)
    diffY = this.y + imageWidth-obj.y;
  else
    diffY =  obj.y + imageWidth-this.y


  if (diffY < 0 || diffY > imageWidth)
    diffY = 0;

  if (diffX * diffY >= 900)
    return (diffX + diffY);
  else
    return 0;
}

function mPuzz_toStart()
/*
  move card to start position
*/
{
  this.moveTo(this.startPos.x, this.startPos.y);
}

function mPuzz_chgPic(n)
/*
  change image of card
*/
{
  if(this.id < cards.length)
    this.img = cards[this.id];

  if (isNC4())
    this.el.document.images[0].src = this.img;

  if (isMSIE() || isMoz())
    this.el.style.background = "url( "+this.img+" )";

  if (isOpera())
    document.images[this.ImgID].src = this.img;
}

function mPuzz_setIndex(n)
/*
  the clicked card is set in front by incrementing zIndex
*/
{
  this.zIndex = n;

  if (isNC4())
    this.el.zIndex = this.zIndex;

  if (isMSIE() || isMoz() || isOpera())
    this.el.style.zIndex = this.zIndex;
}

function createLayer(x, y, img, id)
{
  imgName = pathToImgs + img;
  var s ="\n";

  if (isNC4())
  {
    s += "<layer id= puzz" + id;
    s += " top=" + y  + " left=" + x + " z-index=30>";
    s += " <img src=" + imgName + ">";
    s += "</layer>";
  }

  //if (isMSIE() || isMoz())
  //{
    s += "<div id='puzz" + id + "'";
    s += " style='background-image: url(" + imgName + ");";
    s += " position: absolute; width: " + imageWidth + "px; height: " + imageWidth + "px;";
    s += " top:" + y + "px; left: " + x + "px; z-index: 30;'>";
    s += "</div>";
  //}

  if (isOpera())
  {
    s += "<div id= puzz" + id;
    s += " style='position:absolute; width: " + imageWidth + "px; height: " + imageWidth + "px;";
    s += " top:" + y + "px; left: " + x + "px; z-index: 30;'>";
    s += " <img src='" + imgName + "'>";
    s += "</div>";
  }
  document.open();
  document.write(s);
  document.close();
}

function GetRef(layer)
{
  var ref;

  if (isNC4())
    ref = eval("document." + layer);

  if (isMoz() || isOpera())
    ref = eval(document.getElementById(layer));

  if (isMSIE())
    ref = eval("document.all." + layer);

  return ref;
}

function getX(e)
{
  if (isNC4() || isMoz())
    return e.pageX;

  if (isOpera())
    return e.x+pageXOffset;


  if (isMSIE())
    return event.clientX + document.body.scrollLeft;
}

function getY(e)
{
  if (isNC4() || isMoz())
    return e.pageY;

  if (isOpera())
    return e.y + pageYOffset;

  if (isMSIE())
    return event.clientY + document.body.scrollTop;
}

// browser identification
function isOpera()
{
  var s = navigator.userAgent;
  return (s.lastIndexOf("Opera") > -1);
}

function isMoz()
{
  var s = navigator.userAgent;
  return (s.lastIndexOf("Gecko") > -1);
}

function isNC4()
{
  return (document.layers);
}

function isMSIE()
{
  var s = navigator.userAgent;
  return ((s.lastIndexOf("MSIE 5") > -1 || s.lastIndexOf("MSIE 6") > -1 || s.lastIndexOf("MSIE 7") > -1 || s.lastIndexOf("MSIE 8") > -1) && s.lastIndexOf("Opera") == -1);
  // opera may appear as MSIE5-compatible which is not correct
}
