﻿document.oncontextmenu = disableRightClick;
document.onselectstart = function () { return false; };

function disableRightClick() {
  alert('Source code is COPYRIGHTED. Please, do not reproduce.');
  return false;
}

var clone = null;
var glScore;
var glSScore = 0, giMN = 0;
//		var giHs = 23; //vertical distance between cells
//		var gsWs = 27.3; //horizontal distance between cells
var giTx, giTy; // coordinates of the center of the left top cell
var giEx, giEy; // coordinates of the empty cell
var giCx, giCy; // coordinates of the current cell
var gCX, gCY, gYshift = 0;
var giCC = 0; // current color
var giSx, giSy, giSc; // saved
var iBallBindValue, iUndoFee, iLevel, brwsr, ver;
var blnUndoFlag, blnLoad;
var Cell = new Array(92); // array of cells
var Position = new Array(12); // array of row left cell index
var Path1 = new Array(92); // Path[,0]->Y,Path[,1]->X
var Path2 = new Array(92); // Path[,0]->Y,Path[,1]->X
var MoveCellArray1 = new Array(); // giSx - X coordinate of an empty cell
var MoveCellArray2 = new Array(); // giSy - Y coordinate of an empty cell
var MoveCellArray3 = new Array(); // giSc - color  of a current cell
var MoveCellArray4 = new Array(); // glSScore - score fro this position

function Initialize() {
  blnLoad = true;
  blnUndoFlag = false;
  glScore = 0;
  giSc = 0;

  var s = getBrowser();
  var n = s.indexOf("|");
  brwsr = s.substring(0, n);
  ver = s.substring(n + 1);

  if (brwsr == "IE" && ver == "7.0") gYshift = 11;   //IE7
  if (brwsr == "Safari" || brwsr == "Chrome") gYshift = 2;
  giTx = 315;
  giTy = 151 - gYshift; 
  Position[1] = 0;
  Position[2] = 6;
  Position[3] = 13;
  Position[4] = 21;
  Position[5] = 30;
  Position[6] = 40;
  Position[7] = 51;
  Position[8] = 61;
  Position[9] = 70;
  Position[10] = 78;
  Position[11] = 85;

  document.getElementById("cmdLevel").value = "Novice";
  iBallBindValue = 6;
  iUndoFee = 25;
  iLevel = 3;

  document.onmousedown = Pic_MouseDown;
  if (navigator.appName == "Microsoft Internet Explorer")
    document.onmousedown = Pic_MouseDown;
  else
    document.addEventListener("mousedown", Pic_MouseDown, false);

  if (blnLoad)
    cmdStart_Click();
  else
    Pic_Paint();
}

function cmdStart_Click() {
  var j, k, m;

  blnLoad = false;
  for (m = 0; m < 92; m++) {
    Path1[m] = 0;
    Path2[m] = 0;
    Cell[m] = 0;
  }

  DrawGrayBall(382, 266 - gYshift);

  giMN = 0;
  giEx = 6;
  giEy = 6;
  glScore = 0;
  glSScore = 0;
  document.getElementById("lblScore").value = 0;

  for (k = 1; k < 12; k++) {
    m = GetMax(k);
    for (j = 1; j <= m; j++) {
      Cell[Position[k] + j] = parseInt(iLevel * Math.random() + 2);
    }
  }
  Cell[46] = 1; //Gray
  Pic_Paint();
}

function Pic_Paint() {
  var k, j, m, i, X, Y;

  if (Cell[1] >= 1) {
    for (k = 1; k < 12; k++) {
      m = GetMax(k);
      for (j = 1; j <= m; j++) {
        GetXY(k, j)
        i = Cell[Position[k] + j];
        if (i >= 2)
          DrawBall(i, gCX, gCY);
        else
          DrawGrayBall(gCX, gCY);
      }
    }
  }
}

function DrawImage(i, X, Y) {
  if (i < 6) {
    var obj = document.getElementById("Ball" + i);
    clone = obj.cloneNode(true);
    if (brwsr == "Firefox") {
      clone.style.top = Y + "px";
      clone.style.left = X + "px";
      //alert('X=' + X + ' Y=' + Y);
    }
    else {
      clone.style.pixelTop = Y;
      clone.style.pixelLeft = X;
    }
    clone.style.visibility = 'visible';
    document.body.appendChild(clone);
  }
}

function DrawBall(i, X, Y) {
  DrawImage(i - 2, X - 9, Y - 9);
}

function DrawGrayBall(X, Y) {
  DrawImage(5, X - 9, Y - 9);
}

function cmdLevel_Click() {
  switch (document.getElementById("cmdLevel").value) {
    case "Novice":
      document.getElementById("cmdLevel").value = "Expert";
      iLevel = 4;
      iBallBindValue = 11;
      iUndoFee = 50;
      break;
    case "Expert":
      document.getElementById("cmdLevel").value = "Master";
      iLevel = 5;
      iBallBindValue = 21;
      iUndoFee = 100;
      break;
    case "Master":
      document.getElementById("cmdLevel").value = "Novice";
      iLevel = 3;
      iBallBindValue = 6;
      iUndoFee = 25;
      break;
  }
  cmdStart_Click();
}

function cmdUndo_Click() {
  if (giSc != 0) {
    if (giMN > 0)
      giMN--;
    else
      return;
    giSx = MoveCellArray1[giMN];  //.Sx;
    giSy = MoveCellArray2[giMN];  //.Sy;
    giSc = MoveCellArray3[giMN];  //.Color;
    glSScore = MoveCellArray4[giMN];  //.Score;

    giCx = giSx;
    giCy = giSy;
    giCC = giSc;
    glScore = parseInt(document.getElementById("lblScore").value) - iUndoFee;
    document.getElementById("lblScore").value = glScore;

    blnUndoFlag = true;
    CellMove();
    blnUndoFlag = false;
  }
}

function GetMax(y) {
  var m;

  if (y < 6)
    m = 5 + y;
  else
    m = 17 - y;
  return m;
}

function BorderCheck(x, y) {
  if (x < 1 || x > GetMax(y) || y < 1 || y > 11)
    return false;
  else
    return true;
}

function CheckCC(x, y) {
  // Compares color of cell with giCC, y-vertical coordinate, x-horizontal
  if (x == giCx && y == giCy)
    return false; //exclude current cell
  if (!BorderCheck(x, y))
    return false; //check the border
  if (giCC == Cell[Position[y] + x])
    return true;
  return false;
}

function CellMove() {
  var i, j;

  if (giCC != 0) {
    GetXY(giEy, giEx);
    DrawBall(giCC, gCX, gCY);
    GetXY(giCy, giCx);
    DrawGrayBall(gCX, gCY);
    i = Position[giEy] + giEx;
    j = Position[giCy] + giCx;
    Cell[i] = Cell[j];
    Cell[j] = 1;
    giSx = giEx;
    giSy = giEy;
    giSc = giCC;
    giEx = giCx;
    giEy = giCy;
    if (blnUndoFlag == false) {
      MoveCellArray1[giMN] = giSx;
      MoveCellArray2[giMN] = giSy;
      MoveCellArray3[giMN] = giSc;
      MoveCellArray4[giMN] = glSScore;
      giMN++;
    }
  }
}

function CntLinks(x, y) {
  var iCnt;

  iCnt = 0;
  if (CheckCC(x + 1, y)) iCnt++;
  if (CheckCC(x, y + 1)) iCnt++;
  if (CheckCC(x - 1, y)) iCnt++;

  if (y < 6) {
    if (CheckCC(x - 1, y - 1)) iCnt++;
    if (CheckCC(x, y - 1)) iCnt++;
    if (CheckCC(x + 1, y + 1)) iCnt++;
  }
  else {
    if (y > 6) {
      if (CheckCC(x, y - 1)) iCnt++;
      if (CheckCC(x + 1, y - 1)) iCnt++;
      if (CheckCC(x - 1, y + 1)) iCnt++;
    }
    else {
      if (CheckCC(x - 1, y - 1)) iCnt++;
      if (CheckCC(x, y - 1)) iCnt++;
      if (CheckCC(x - 1, y + 1)) iCnt++;
    }
  }
  return iCnt;
}

function FindPath() {
  var i, x, y, m, n;

  for (m = 1; m < 92; m++) {
    Path1[m] = 0;
  }
  Path1[1] = giCy;
  Path2[1] = giCx;
  m = 1;
  n = 1;
  while (true) {
    while (IsNext(m)) {
      m++;
      if (Cell[Position[Path1[m]] + Path2[m]] == 1)
        return true;
    }

    if (m == n)
      return false;
    y = Path1[m];
    x = Path2[m];
    for (i = m; i >= n + 1; i--) {
      Path1[i] = Path1[i - 1];
      Path2[i] = Path2[i - 1];
    }
    Path1[n] = y;
    Path2[n] = x;
    n++;
  }
}

function FindNext(x, y) {
  var i, n;

  if (!BorderCheck(x, y))
    return false; //check the border
  for (i = 1; i < 92; i++) {
    if (Path1[i] == 0)
      break;
    if (Path1[i] == y && Path2[i] == x)
      return false;
  }

  n = Position[y] + x;
  if (giCC == Cell[n] || Cell[n] == 1) // the same color or empty space
  {
    Path1[i] = y;
    Path2[i] = x;
    return true;
  }
  return false;
}

function GetXY(k, j) {
  //get pixels coordinates
  //gCY = parseInt(giTy + (k - 1) * giHs);
  //gCX = giTx - (GetMax(k) - 6) * gsWs / 2 + (j - 1) * gsWs;
  gCY = parseInt(giTy + (k - 1) * 23);
  gCX = parseInt(giTx - parseFloat((GetMax(k) - 6) * 13.65) + parseFloat((j - 1) * 27.3));
}

function IsNext(iPath) {
  var y, x;

  y = Path1[iPath];
  x = Path2[iPath];

  if (y < 6) {
    if (FindNext(x + 1, y)) return true;
    if (FindNext(x, y - 1)) return true;
    if (FindNext(x - 1, y - 1)) return true;
    if (FindNext(x - 1, y)) return true;
    if (FindNext(x, y + 1)) return true;
    if (FindNext(x + 1, y + 1)) return true;
  }
  else {
    if (y > 6) {
      if (FindNext(x + 1, y)) return true;
      if (FindNext(x + 1, y - 1)) return true;
      if (FindNext(x, y - 1)) return true;
      if (FindNext(x - 1, y)) return true;
      if (FindNext(x - 1, y + 1)) return true;
      if (FindNext(x, y + 1)) return true;
    }
    else {
      if (FindNext(x + 1, y)) return true;
      if (FindNext(x, y - 1)) return true;
      if (FindNext(x - 1, y - 1)) return true;
      if (FindNext(x - 1, y)) return true;
      if (FindNext(x - 1, y + 1)) return true;
      if (FindNext(x, y + 1)) return true;
    }
  }
  return false;
}

function Pic_Click() {
  blnUndoFlag = false;
  CellMove();
}

function Pic_MouseDown(e) {
  if (e == null) e = window.event;
  var i, x0, X, Y;
  var x1, y1, x2, y2, iCnt;
  var dx, dy;
  X = e.clientX;
  Y = e.clientY;
  //window.status = 'X=' + X + ' Y=' + Y;		
  e.cancelBubble = true;
  e.returnValue = false;

  //giCy = parseInt((Y - giTy + giHs / 2) / giHs) + 1;    //row #
  giCy = parseInt(parseFloat((Y - giTy + 11.5) / 23) + 1);    //row #

  //x0 = parseInt(giTx - (GetMax(giCy) - 6) * gsWs / 2);
  x0 = parseInt(giTx - parseFloat((GetMax(giCy) - 6) * 13.65));
  giCx = parseInt(parseFloat(((X - x0) / 27.3 + 0.5)) + 1);       //# of cell in row

  if (!BorderCheck(giCx, giCy)) {
    giCC = 0;
    return;
  }

  giCC = Cell[Position[giCy] + giCx];     //color of the clicked cell
  for (i = 2; i < 7; i++)
    if (giCC == i) break;   //# in color table
  if (i > 6)     //not a ball
  {
    giCC = 0;
    return;
  }

  // Check for allowed move
  iCnt = CntLinks(giEx, giEy);

  if (iCnt == 0) {
    giCC = 0;
    return;
  }
  else   //Are the empty cell and current cell neighbours?
  {
    GetXY(giCy, giCx);
    x1 = gCX;
    y1 = gCY;
    GetXY(giEy, giEx);
    x2 = gCX;
    y2 = gCY;
    dx = x1 - x2;
    dy = y1 - y2;
    //if ((parseFloat(dx * dx) + parseFloat(dy * dy)) > parseFloat(gsWs * gsWs * 1.1))
    if ((parseFloat(dx * dx) + parseFloat(dy * dy)) > 819.819) {
      if (iCnt < 2 || FindPath() == false) {
        giCC = 0;     //current color=0 -> not neighbours
        return;
      }
    }
    iCnt -= CntLinks(giCx, giCy);
    glSScore = glScore;
    glScore = glScore + parseInt(iCnt * iBallBindValue) - 1;
    document.getElementById("lblScore").value = glScore;
    Pic_Click();
    document.getElementById("mainDiv").focus();
  }
}



