var typicalPuzzle = {keys:[0,2],
           rows: [[{img:'Pig'},{img:'Pig'},{img:'Rat'}],
                  [{img:'Pig'},{img:'Rat'},{img:'Pig'}],
                  [{img:'Rat'},{img:'Pig'},{img:'Pig'}],
                  [{img:'Pig'},{img:'Rat'},{img:'Rat'}]
                 ]
          } 

function ol(){
  var p = mkPuzzle(4,3,2,3);
  showPuzzle(newPuzzle());
  startTimer();
}
var images = 'Dog Dragon Goat Horse Monkey Ox Pig Rabbit Rat Rooster Snake Tiger'.split(' ');
var symbols = '8727 8728 8734 8736 8743 8744 8745 8746 8782 8782 8785 8902'.split(' ');
var chess   = '9812 9813 9814 9815 9816 9817 9818 9819 9820 9821 9822 9823'.split(' ');
var zodiac = listFrom(9800,12);
var listlist = [mapsym(listFrom(9856,6))
               ,mapsym(listFrom(65,6))
               ,mapsym(listFrom(9812,6))
               ,mapsym(listFrom(9800,6))
               ,mapsym(listFrom(9806,6))
               ,mapsym(listFrom(9874,6))
               ];
var puzzleCount = 0;
// "111223" means first three are level 1, next 2 are level 2 next one is level 3
var levelList = "11122233333334554";
var rowList   = "45645655667899999";
var yourScore = 0;

function listFrom(x,y){
  var l=new Array();
  for (var i=0;i<y;i++) l[i] = x+i;
  return l;
}

function mapsym(l){
  var r= new Array();
  for (var i=0;i<l.length;i++)
    r[i] = {img:'http://sqlzoo.net/~andrew/brain/unicode/'+l[i]+'.png'};
  return r;
}

function mapimg(l){
  var r= new Array();
  for (var i=0;i<l.length;i++)
    r[i] = {img:'http://www.iconarchive.com/icons/troyboydesign/delightful-zodiac/'+l[i]+'-32x32.png'};
  return r;
}

function newPuzzle(){
  //function mkPuzzle(nRows,nCols,nKeys,nOpts){
  puzzleCount++;
  var level  = levelList.charAt(puzzleCount-1);
  var nItems = rowList.charAt(puzzleCount-1);
  if (level==1)
    return mkPuzzle(nItems,1,1,nItems);
    //We make a level 1 puzzle
  if (level==2)
    return mkPuzzle(nItems,2,2,3);
  if (level==3)
    return mkPuzzle(nItems,3,2,3);
  if (level==4)
    return mkPuzzle(nItems,4,2,3);
  if (level==5)
    return mkPuzzle(nItems,4,3,2);
  alert("no more puzzles");
}

function mkPuzzle(nRows,nCols,nKeys,nOpts){
  //Generate all combinations of nOpts
  var n = Math.pow(nOpts,nKeys);
  var r = new Array();
  for (var i=0;i<n;i++){
    r[i] = new Array();
    var tmp=i;
    for (var j=0;j<nKeys;j++){
      r[i].push(tmp % nOpts);
      tmp = Math.floor(tmp/nOpts);
    }
  }
  scramble(r);
  r.splice(nRows-1,1+n-nRows);
  r.push(r[0].concat([]));
  scramble(r);
  for (var i=0;i<nRows;i++)
    for (var j=0;j<nCols-nKeys;j++)
       r[i].push(Math.floor(Math.random()*nOpts));
  var cols = new Array();
  for (var i=0;i<nCols;i++) cols[i]=i;
  var perms=new Array();
  for (var i=0;i<nCols;i++){
    perms[i] = new Array();
    for (var j=0;j<6;j++)
      perms[i][j]=j;
    scramble(perms[i]);
  }
  scramble(cols);
  var syms = new Array();
  for (var i=0;i<listlist.length;i++) syms[i]=i;
  scramble(syms);
  var keys = new Array();
  for (var i=0;i<nKeys;i++)
    keys.push(pos(i,cols));
  var rows = new Array();
  for (var i=0;i<nRows;i++){
    rows[i] = new Array();
    for (var j=0;j<nCols;j++){
      //var k = perms[j][r[i][cols[j]]];
      var k = r[i][cols[j]];
      k = perms[j][k];
      rows[i].push(listlist[syms[j]][k]);
    }
  }
  return {keys:keys,rows:rows};
}

function pos(i,l){
//Return the position of i in array l
  for (var x=0;x<l.length;x++)
    if (i==l[x]) return x;
  alert(x+' not found in '+l);

}

function scramble(r){
  for (var i=0;i<r.length;i++){
    var tmp = r[i];
    var swp = Math.floor(Math.random()*r.length);
    r[i] = r[swp];
    r[swp]=tmp; 
  }
}

var currentPuzzle;
var bw = 100; var gap=10;
var bhf = 20;
var bh = 44;
var gsw = 600;

function showPuzzle(t){
  currentPuzzle = t;
  var gs = $('gameSpace');
  while (gs.firstChild) gs.removeChild(gs.firstChild);
  var nCols = t.rows[0].length;
  for (var i=0;i<nCols;i++){
    var d = Builder.node('div',{id:'ch'+i,'class':'head'},
                         ['\u00A0']);
    var x = (gsw-bw*nCols-gap*(nCols-1))/2+i*(bw+gap);
    Element.setStyle(d,{left:x+'px',
                        width:bw+'px',
                        top:0+'px'});
    gs.appendChild(d);
  }
  for (var i=0;i<t.keys.length;i++){
    var id = 'ch'+t.keys[i]
    $(id).appendChild(Builder.node('span',{},['key']));
  }
  for (var i=0;i<t.rows.length;i++){
    var r=t.rows[i];
    var d = Builder.node('div',{id:'rw'+i,'class':'row',onclick:'clickRow(this)'});
    var xl = (gsw-bw*nCols-gap*(nCols-1))/2;
    Element.setStyle(d,{position:'absolute',left:xl+'px',
                        'top':((bh+gap)*i+bhf)+'px',
                        width:(bw+gap)*nCols+'px',
                        height:bh+'px'});
    for (var j=0;j<r.length;j++){
      var e = Builder.node('div',{});
      var x = j*(bw+gap);
      Element.setStyle(e,{position:'absolute',
                          left:x+'px',
                          width:bw+'px',
                          'textAlign':'center'});
      if (r[j].img){
        e.appendChild(Builder.node('img',{src:r[j].img}));
        d.appendChild(e);
      }else if(r[j].str){
        e.appendChild(Builder.node('span',{'class':'symbol'},[ r[j].str]));
        d.appendChild(e);
      }
      //if (r[j].str)
      //  e.appendChild(Builder.node('span',{}.[r[j].str]));

    gs.appendChild(Builder.node('a',{id:'a'+j,href:'#'},[d]));    
    }
  }
  gs.t = t;
  //startTimer();
}

function sameRow(r1,r2){
  var cp = currentPuzzle;
  var gs = $('gameSpace');
  var i1 = r1.substring(2);
  var i2 = r2.substring(2);
  var k1='';var k2='';
  for (var i=0; i<cp.keys.length;i++){
    if (Object.toJSON(cp.rows[i1][cp.keys[i]]) !=
        Object.toJSON(cp.rows[i2][cp.keys[i]])) return false;
  }
  return true;
}

function clickRow(row){
  var gs = $('gameSpace');
  if((gs.firstClick === undefined) || (gs.firstClick == 0)){
    gs.firstClick = 1;
    gs.firstClickId = row.id
    row.setStyle({backgroundColor:'pink'})
  }else{
    row.setStyle({backgroundColor:'pink'})
    if(row.id != gs.firstClickId){
      gs.firstClick = 0;
      var chk = sameRow(row.id,gs.firstClickId);
      if (chk)
        yourScore++;
      dispGood(chk,row,$(gs.firstClickId));
//      row.setStyle({backgroundColor:'white'})
//      $(gs.firstClickId).setStyle({backgroundColor:'white'})

    }else{
      row.setStyle({backgroundColor:'white'});
      gs.firstClick = undefined;
    }
  }
}

function dispGood(flg,d1,d2){
  //new Effect.Appear('Good',{ duration: 5,afterFinish: function(){},beforeFinish: function(){})
  $('score').innerHTML = yourScore;
  if(flg){
    //text = '\u263A'
    var num = 9786;
    text = String.fromCharCode(num);
  }else{
    var num = 9787;
    text = String.fromCharCode(num);
  }

  var gs = $('gameSpace');
  var d = Builder.node('div',{id:text,style:'background-color:yellow; font-size:48px; text-align: center;height:50px;width:100px;position:absolute;left:200px;top:200px'},[text])
  gs.appendChild(d);
  if(flg){
      new Effect.Appear(d,{ duration: .2,
                    afterFinish: function(){
                                  new Effect.Fade(d,
                                  {duration:.2,afterFinish: function(){
                                            // New Puzzle
                                            //gs.appendChild('');
                                            showPuzzle(newPuzzle()); 
                                                  }
                                  }
                                )
                    }
                  })
  }else{
    new Effect.Appear(d,{ duration: .2,
                    afterFinish: function(){
                                  new Effect.Fade(d,
                                  {duration:.2,afterFinish: function(){
                                  d1.setStyle({backgroundColor:'white'});
                                  d2.setStyle({backgroundColor:'white'});
                                            // New Puzzle
                                                  }
                                  }
                                )
                    }
                  })
  }

}

function startTimer(){
  var tick = 60;
  
  new PeriodicalExecuter(function(pe) {
    $('ticker').innerHTML = tick--;
    if (tick==0){
      pe.stop();
      $('ticker').innerHTML = '0';
      $('gameSpace').hide();
    } 
  }, 1);
}

