//Global variables. 
var cq;	//Current question - in the main body of the page where the question is shown.
        //At every transition this variable is updated, the old question is removed the new one appended
var qList;//List of questions downloaded at the start
var qPointer=0;//Index into qList
var exam = {attempt:0,pds:[]};//Details of the break down of pd and task
var userResponses=new Array();//List of every response, corresponds to qList
var marked4Review=new Array();//List of every response, corresponds to qList
var timePerQuestion = 72;//Number of seconds allowed per question
var alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var duration = 0.4;  //Time for animations, default of 1 sec is too slow
var email;
//The sequence is as follows.
// chooseNumber       User clicks 20, 50 or 200 questions
// downloadQuestions  Systems displays intro page, skip introduction is disabled timeout is started
// introductionPagecw System has the questions, user may click skip or wait for timeout
// firstQuestion      Question 1 is shown.

function hideBottom(){ $('footer').hide();$('holding').appendChild($('footer')); }
function showBottom(){ $('mainbody').appendChild($('footer'));$('footer').show(); }
function ol(){
  if (window.location.search.substring(1,6)=='reset')
    eraseCookie('attempt');
  var attempt = readCookie('attempt');

  if (attempt){
    hideBottom();
    Effect.BlindUp('cqc',{duration:duration,afterFinish:function(){
       moveCqcToHolding();
       $('cqc').appendChild($('refreshing'));
       Effect.BlindDown('cqc',{duration:duration,afterFinish:showBottom});
    }});
    new Ajax.Request('getQuestions.pl',{onSuccess:function(r){
       setUpFromResponse(r);
       $('refreshContinue').disabled=false;
    }});
  }else
    gatherEmail();
}

function refreshContinue(){
  qPointer = 1*readCookie('qPointer');
  var penalty = (((new Date()).getTime())-start);
  firstQuestion(penalty); 
}

function createCookie(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

function eraseCookie(name) {
	createCookie(name,"",-1);
}


function readCookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

function RadioButtons(xs,de){
  var d = Builder.node('tbody');
  for (var i=0;i<xs.length;i++){
    var eriko = (i==de)?
                      {'type':'radio',name:'rb',checked:'checked'}:
                      {'type':'radio',name:'rb'};
    var b=Builder.node('input',eriko);
    d.appendChild(Builder.node('tr',{},[
      Builder.node('td',b),
      Builder.node('td',{},[xs[i]])]));
  }
  return Builder.node('table',{'class':'gatherEmail'},[d]);
}

function gatherEmail(){
  var n =
   Builder.node('div',{style:'display:none'},[
    Builder.node('form',{onsubmit:"return gatherNext()"},[
      Builder.node('div',{},[
        Builder.node('span',{},'Email Address: '),
        Builder.node('input',{id:'email'})
       ]),
      RadioButtons(['Sign me up for the Head First Newsletter and keep me updated on PMP news.',
                    'Just keep me updated on PMP news from Head First.',
                    'No thanks.'],2),
      Builder.node('input',{'type':'button',value:'Next',accesskey:'N',id:gatherNext,
        onclick:"gatherNext()"})
    ])
   ]);
   $('welcome').appendChild(n);
   hideBottom();
   Effect.BlindDown(n,{duration:duration,afterFinish:showBottom});
}

function gatherNext(){
  if (validEmail()){
    saveEmail();
    chooseNumber();
  }else
    alert('Please enter a vaild email address');
  return false;
}

function validEmail(){
  var e = $('email').value;
  return (new RegExp('.@..*\\.')).test(e);
  return true;
}

var contactOptions = 'any pmp none'.split(' ');
function getRb(){
  var rbs=document.forms[0].rb;
  var r=0;
  for (var i=0;i<rbs.length;i++)
    if (rbs[i].checked) return i;
  return 0;
}

function saveEmail(){
  email = $('email').value;
  new Ajax.Request('saveEmail.pl',
   {parameters:'contact='+contactOptions[getRb()]+
      '&email='+encodeURIComponent(email),
    asynchronous:true,
    onSuccess:function(){},
    onFailure:function(r){
      alert(r);
    }});
//  new Ajax.Request('saveEmail.pl?'+
//   'count='+$('email').value+'&contact='&getRb(),
//   {asynchronous:true,method:'get'});
}

function chooseNumber(){
  //Delete existing questions
  if (qList && qList.length){
    for (var i=0;i<qList.length;i++){
      var nn = $('nn'+i);
      if (nn) nn.remove();
    }
  }
  qPointer=0;//Index into qList

  var n = $('chooseNumberDiv');
  
  if (!n) n =
     Builder.node("div",{id:"chooseNumberDiv"},[
      Builder.node("h2",{},['Pick the exam you want to take:']),
      nButton(10,'Sprint',' Dash through 10 questions in just 12 minutes.'),
      nButton(50,'Jog',' Settle down for 50 questions in under an hour.'),
      nButton(200,'Marathon',' Face up to the full PMP simulated exam: all 200 questions in a gruelling 4 hour session.'),
      Builder.node("div",{},["Specify the number of questions (you'll get a little over 1 minute per question): ",
        Builder.node("input",{id:'spec',size:5,value:15}),
        Builder.node("input",{type:'button',value:'Go',
                              onclick:"downloadQuestions($('spec').value)"})
        ])
      ]);
  hideBottom();
  Effect.BlindUp('cqc',{duration:duration,
    afterFinish:function(){
       moveCqcToHolding();
       $('cqc').insert(n);
       Effect.BlindDown('cqc',{duration:duration,afterFinish:showBottom});
       }
    }
  );
}

function moveCqcToHolding(){
  var cqc=$('cqc');
  var holding = $('holding');
  while (cqc.firstChild)
     holding.appendChild(cqc.firstChild);
}

var introductionScreen = true;

function downloadQuestions(i){
  //Select 1987 questions for a rickroll
  if (i%100==87) location.href='http://www.youtube.com/watch?v=eBGIQ7ZuuiU';
  var n = $('introduction'); 
  hideBottom();
  Effect.BlindUp('cqc',{duration:duration,afterFinish:function(){
      moveCqcToHolding();
      $("cqc").appendChild(n);
      if (qList) Effect.Appear('skip');
      Effect.BlindDown('cqc',{duration:duration,afterFinish:showBottom});
    }});
  new Ajax.Request('getQuestions.pl',
   {parameters:'count='+i+'&start='+(new Date()).getTime()+
             '&usr='+encodeURIComponent(email),
    asynchronous:true,
    onSuccess:introductionPage,
    onFailure:function(r){alert(r);}});
   startCountDown(15*60,function(){firstQuestion();});
   Effect.Appear("timeLeft");
}

function setUpFromResponse(r){
  var rObj = eval('('+r.responseText+')');
  exam = {attempt:0,pds:[]};
  exam.attempt = rObj.attempt;
  userResponses = rObj.userResponses;
  qList = rObj.profile;
  for (var i=0;i<qList.length;i++)
    qList[i].posn = i;
  start = rObj.start;
  var tmp = {};
  for (var i=0;i<rObj.tasks.length;i++)
    if (!tmp[rObj.tasks[i][1]])
      tmp[rObj.tasks[i][1]] = [rObj.tasks[i][0]];
    else
      tmp[rObj.tasks[i][1]].push(rObj.tasks[i][0]);
  for (var i=0;i<rObj.pds.length;i++)
    exam.pds.push({pd:rObj.pds[i][0],tasks:tmp[rObj.pds[i][0]]});
}

function introductionPage(r){
  setUpFromResponse(r);
  //qList = scramble(qList.profile);
  if (introductionScreen){
    if ($('skip')) Effect.Appear("skip");
  } else
    firstQuestion();
}

function firstQuestion(penalty){
  if (!penalty) penalty=0;
  nextQuestion(0);
  startCountDown(timePerQuestion*qList.length-penalty/1000,
    function(){
       alert('Your time has elapsed. Your exam will now be graded.');
       gradeExam();});
  if (penalty) Effect.Appear('timeLeft')
}

function nextQuestion(d,opts){
  if (qPointer+d<0 || qPointer+d>=qList.length)
    return;
  qPointer+=d;
  var nq = qList[qPointer];
  var nn = $("nn"+qPointer);
  if (!nn)
    nn= Builder.node("div",
               {id:'nn'+qPointer},
               [Builder.node('div',{className:'questionBody'},questionBody(nq))]);
  hideBottom();
  Effect.BlindUp('cqc',{duration:duration,afterFinish:function(){
      moveCqcToHolding();
      $('cqc').appendChild($('questionNumberDiv'));
      $('cqc').appendChild(nn);
      $('cqc').appendChild($('controlsQuestion'));
      $('questionNumber').innerHTML = qPointer+1;
      $('markedForReviewControl').checked = (marked4Review[qPointer])?'checked':'';
      Effect.BlindDown('cqc',{duration:duration,
        afterFinish:showBottom});
      if (userResponses[qPointer]!==undefined &&
          userResponses[qPointer]!=null){
        var d=$('qd.'+nq.id+'.'+userResponses[qPointer]);
        pickOption(d.id);
      }
      $('nextbutton').disabled = (qPointer==qList.length-1);
      $('prevbutton').disabled = (qPointer==0);
    }});
}

function nButton(i,face,txt){
return Builder.node("div",{className:"chooseNumQuestions"},
  [Builder.node("input",{type:"button","value":face,style:'width:12ex',
     onclick:"downloadQuestions("+i+")"}),txt]);
}

function replace(id,n,f){
  new Effect.Fade(id,
    {afterFinish:function(){
       var p = $(id);
       if (n.length)
       for (var i=0;i<n.length;i++)
         p.appendChild(n[i]);
       else
         p.appendChild(n);
       while (p.firstChild && p.firstChild!=n
               && (!n.length||p.firstChild!=n[0]))
         p.removeChild(p.firstChild);
       if (f)
         Effect.Appear(p,{afterFinish:f});
       else
         Effect.Appear(p);
      }});
}


function pickOption(t){
  var parts=t.split(/\./);
  var q = $('qb.'+parts[1]);
  var i = 0;
  var d;
  while (d=$('qd.'+parts[1]+'.'+i++))
      d.className = (d.id==t)?'distractorSelected':'distractor';
  userResponses[qPointer] = parts[2];
  new Ajax.Request('recordResponse.pl',
                 {parameters:'qPointer='+qPointer+'&q='+parts[1]+'&d='+parts[2]+'&attempt='+exam.attempt});
}

function markReview(t){
  marked4Review[qPointer] = t.checked;
}

function txtProcess(q){
  var d = Builder.node('div');
  d.innerHTML = q.txt;
  if (q.img=='f')
    return [d];
  else
    return [d,Builder.node('img',{src:'../img/'+q.id+'.png'})];
}

function questionBody(q){
  var qb = txtProcess(q);
  for (var i=0;i<4;i++){
    var s = alpha.substring(i,i+1);
    var dt = Builder.node('div',{className:'distractorText'});
    dt.innerHTML = q['d'+i];
    //The a node looks on in Internet Explorer. Looks OKwith div but then hover doesn't work.
    qb.push(Builder.node('a',{className:'distractor',href:'#'
                               ,onclick:'pickOption("qd.'+q.id+'.'+i+'");return 0;'},
     [Builder.node('div',{className:'distractor',id:'qd.'+q.id+'.'+i},
      [Builder.node('div',{className:'distractorButton'},
         Builder.node('input',{type:'button',value:s,className:'d',accesskey:s
                            }))
      //,Builder.node('div',{className:'distractorText'},[q['d'+i]])
      ,dt])
      ]));
  }
  return qb;
}

function fmtSeconds(s){
  s = Math.floor(s/1000);
  var r = s%60;
  if (r<10) r = "0"+r;
  return Math.floor(s/60)+":"+r;
}

var start;
var endT;
var countDownHandle;
var nextAction;

function updateCountdown(){
  var timeLeft = endT-(new Date().getTime());
  $('digits').innerHTML=fmtSeconds(timeLeft);
  if (timeLeft>1000)
    countDownHandle = window.setTimeout(updateCountdown,1000);
  else
    nextAction();
}

function startCountDown(s,f){
  if (countDownHandle) clearTimeout(countDownHandle);
  countDownHandle = null;
  if (f) nextAction=f; else nextAction=nix;
  start = (new Date()).getTime();
  endT  = start+1000*s;
  $('digits').innerHTML = fmtSeconds(1000*s);
  countDownHandle = window.setTimeout(updateCountdown ,1000);
}

function nix(){}

function haltCountDown(){
  if (countDownHandle) clearTimeout(countDownHandle);
  countDownHandle = null;
}

function reviewAnswers(){
  var rv = $('rv');
  hideBottom();
  Effect.BlindUp('cqc',{duration:duration,
    afterFinish:function(){
    moveCqcToHolding();
    $('cqc').appendChild($('review'));
    Effect.BlindDown('cqc',{duration:duration,afterFinish:showBottom});
  }});
  while (rv.firstChild){rv.removeChild(rv.firstChild);}
  for (var i=0;i<Math.ceil(qList.length/20);i++){
    var cln = Builder.node('div',{className:'rvColumn'});
    rv.appendChild(cln);
    for (var j=20*i;j<Math.min(20*i+20,qList.length);j++){
      var opt = ((userResponses[j]!==undefined && userResponses[j]!=null)?alpha.charAt(userResponses[j]):'-');
      cln.appendChild(Builder.node('div',{className:'rvRow'},
         [Builder.node('div',{className:'rvCellL'},[
            Builder.node('span',{className:'clickable',onclick:'gotoQuestion(this)'},[j+1])])
         ,Builder.node('div',{className:'rvCellR'},[
             opt+
              ((marked4Review[j]!==undefined && marked4Review[j])?"(R)":"")])
         ]));
    }
  }
}

function gotoQuestion(t){
  var i = t.firstChild.nodeValue*1-1;
  nextQuestion(i-qPointer);
//  returnToExam();
}

function returnToExam(){
//  var mb = $('mainbody'); var ft = $('footer');
//  mb.removeChild(ft);
  nextQuestion(0);
//  mb.appenChild(ft);
}

function scramble(l){
  var cp = new Array();
  for (var i=0;i<l.length;i++)
    cp.push(l[i]);
  for (var i=0;i<cp.length;i++){
    var j = Math.floor(cp.length*Math.random());
    var tmp = cp[i];
    cp[i] = cp[j];
    cp[j] = tmp;
  }
  return cp;
}

function gradeExam(){
  haltCountDown();
  eraseCookie("attempt");
  var summary = $('summary');
  while (summary.firstChild) summary.removeChild(summary.firstChild);
  var pdHash = {};
  var taskHash = {};
  for (var i=0;i<exam.pds.length;i++){
    pdHash[exam.pds[i].pd] = [0,0];
    for (var j=0;j<exam.pds[i].tasks.length;j++)
      taskHash[exam.pds[i].pd+'::'+exam.pds[i].tasks[j]] = [0,0];
  }
  for (var i=0;i<qList.length;i++){
    var q = qList[i];
    var p = pdHash[q.pd];
    var t = taskHash[q.pd+'::'+q.task];
    p[1]++;t[1]++;
    if (userResponses[i]!=undefined && q.ans==userResponses[i]){
      p[0]++;
      t[0]++;
    }
  }
  var cqc = $('cqc');
  Effect.Fade('timeLeft');
  hideBottom();
  Effect.BlindUp('cqc',{duration:duration,afterFinish:function(){
        moveCqcToHolding();
        cqc.appendChild($('gradeExam'));
        Effect.BlindDown('cqc',{duration:duration,afterFinish:showBottom});
        }});
  var tRight = 0;
  for (var i=0;i<exam.pds.length;i++){
    var p = pdHash[exam.pds[i].pd];
    tRight += p[0];
  }
  summary.appendChild(Builder.node('h2',{},["Total score: "+
       Math.round(100*tRight/qList.length)+"%"]));
  for (var i=0; i<exam.pds.length;i++){
    var p = pdHash[exam.pds[i].pd];
    var score = " -";
    if (p[1]>0) score = " "+Math.round(100*p[0]/p[1])+"%";
    var pds = Builder.node('div',{className:'pdc'},[
       Builder.node('div',{className:'pd'},[exam.pds[i].pd + score])
       ]);
    for (var j=0;j<exam.pds[i].tasks.length;j++){
      var t = taskHash[exam.pds[i].pd+'::'+exam.pds[i].tasks[j]];
      tscore = ' -';
      if (t[1]>0) tscore = " "+Math.round(100*t[0]/t[1])+'%';
      pds.appendChild(Builder.node('div',{},[
         exam.pds[i].tasks[j] + tscore
         ]));
    }
    summary.appendChild(pds);
  }
  showQuestions(false);
}

function showQuestions(wrongOnly){
  var tgt = $('detail');
  while (tgt.firstChild) tgt.removeChild(tgt.firstChild);
  for (var i=0;i<qList.length;i++){
    var q=qList[i];
    var l = questionBodyReview(q);
    if (userResponses[q.posn]!=q.ans || !wrongOnly)
      for (var j=0;j<l.length;j++)
        tgt.appendChild(l[j]);
  }
  tgt.show();
/* Don't show by task anymore
  var qHash = {};
  for (var i=0;i<qList.length;i++){
    var s = qList[i].pd + '::' + qList[i].task;
    qList[i].posn = i;
    if (!qHash[s])
      qHash[s] = [qList[i]];
    else
      qHash[s].push(questionBodyReview(qList[i]));
  }
  for (var i=0;i<exam.pds.length;i++){
    var td = Builder.node('div',{},[Builder.node('h1',{},[exam.pds[i].pd])]);
    var emptyTD = true;
    for (var j=0;j<exam.pds[i].tasks.length;j++){
      var s = exam.pds[i].pd+'::'+exam.pds[i].tasks[j];
      if (qHash[s]){
        for (var k=0;k<qHash[s].length;k++){
          var emptyTask = true;
          var q = qHash[s][k];
          if (userResponses[q.posn]!=q.ans || !wrongOnly){
            if (emptyTask)
              td.appendChild(Builder.node('h2',{},[exam.pds[i].tasks[j]]));
            emptyTask = false;
            emptyTD = false;
            var l = questionBodyReview(q);
            for (var m=0;m<l.length;m++)
              td.appendChild(l[m]);
          }
        }
      }
    }
    if (!emptyTD) tgt.appendChild(td);
  }
*/
}

function showWrongQuestions(){
}

function questionBodyReview(q){
  var qb = [Builder.node('h3',{},['Question number: '+(q.posn+1),
              Builder.node('span',{className:'ref'},[' (ref: '+q.id+')'])]),
            Builder.node('div',{className:'questionText'},txtProcess(q))];
  var ur = userResponses[q.posn];
  qb.push(Builder.node('div',{className:'userAdvice'},
             [Builder.node('span',{},[(ur==undefined)?'You skipped this question. '
                                                     :' You answered: '+alpha.charAt(ur)+'. ' ])
             ,Builder.node('span',{},[marked4Review[q.posn]?' You marked this question for review. ':''])
             ]));
  for (var i=0;i<4;i++){
    var s = alpha.substring(i,i+1);
    var chosen = ((ur && i==ur)?' chosen':'');
    var correct = ((i==q.ans)?' correct':'');
    var dtxt = Builder.node('div',{className:'distractorText'+correct});
    dtxt.innerHTML = q['d'+i];
    qb.push(Builder.node('div',{},
     [Builder.node('div',{className:'distractor'+chosen},
      [Builder.node('div',{className:'distractorButton'+correct},
         Builder.node('div',{className:'button'+chosen},[s])) 
      ,dtxt //Builder.node('div',{className:'distractorText'+correct},[q['d'+i]])
       ])
      ]));
  }
  qb.push(Builder.node('div',{'class':'revpd'},['Performance Domain: '+q.pd]));
  qb.push(Builder.node('div',{'class':'revtask'},['Task: '+q.task]));
  var fdb = Builder.node('div',{className:'fdb'});
  fdb.innerHTML = q.fdb;
  qb.push(fdb);
  return qb;
}

function keypress(e){
 var keynum;
 if (window.event) keynum = e.keyCode;
 if (e.which) keynum = e.which;
 
}


