﻿/*
  Copyright (c) 2003, 2008 Nesterovsky bros.  All rights reserved.

  Annotation presentation component.

  You must not remove this notice, or any other, from this software.
*/

function Annotation(board, annotationElement)
{
  var self = this;
  
  document.onchanged = function()
  {
    var game = document.games[self._gameIndex];

    if (game != self._game)
    {
      self._create();
    }
  };

  this._document = document;
  this._board = board;
  this._annotationElement = annotationElement;
}

/* Primitive navigation. */

Annotation.prototype.start = function()
{
  if (!this._game)
  {
    return;
  }
  
  this._moveElement = null;
  
  var element = this._findAnnotation(this._moveElement);
  
  if (element)
  {
    element.click();
  }
  else
  {
    this._selectAnnotation(element);
  }
}

Annotation.prototype.back = function()
{
  if (!this._game)
  {
    return;
  }
  
  if (!this._moveElement)
  {
    this.start();
    
    return;
  }
  
  this._moveElement = this._moveElement.prevMove ? this._moveElement.prevMove : 
    this._moveElement.parentMove ? this._moveElement.parentMove.prevMove : null ;
  
  var element = this._findAnnotation(this._moveElement);
  
  if (element)
  {
    element.click();
  }
  else
  {
    this._selectAnnotation(element);
  }
}

Annotation.prototype.forward = function()
{
  if (!this._game)
  {
    return;
  }
  
  if (!this._moveElement)
  {
    this._moveElement = this._game.moves[0];
  }
  else if (this._moveElement.nextMove)
  {
    this._moveElement = this._moveElement.nextMove;
  }
  
  var element = this._findAnnotation(this._moveElement);
  
  if (element)
  {
    element.click();
  }
  else
  {
    this._selectAnnotation(element);
  }
}

Annotation.prototype.end = function()
{
  if (!this._game)
  {
    return;
  }
  
  this._moveElement = this._game.moves[game.moves.length - 1];
  
  var element = this._findAnnotation(this._moveElement);
  
  if (element)
  {
    element.click();
  }
  else
  {
    this._selectAnnotation(element);
  }
}

Annotation.prototype.getAnnotationElement = function()
{
  return this._annotationElement;
}

Annotation.prototype.getDocument = function()
{
  return this._document;
}

Annotation.prototype.setDocument = function(value)
{
  this._document = value;
}

Annotation.prototype.getGameIndex = function()
{
  return this._gameIndex;
}

Annotation.prototype.setGameIndex = function(value)
{
  if (this._gameIndex != value)
  {
    this._gameIndex = value;
    this._create();  
  }
}

Annotation.prototype.onselectmove = null;
Annotation.prototype.move = null;

/* private members. */

// TODO: find better solution temporary.
Annotation.prototype._internalActiveMoveStyle = 
  "background-color: highlight; color: highlighttext";

Annotation.prototype._board = null;
Annotation.prototype._activeMove = null;
Annotation.prototype._annotationElement = null;
Annotation.prototype._moveElement = null;
Annotation.prototype._annotationMap = null;

Annotation.prototype._document = null;
Annotation.prototype._gameIndex = -1;
Annotation.prototype._game = null;

Annotation.prototype._updatingBoard = false;

/*
  Clears annotation.
*/
Annotation.prototype._clear = function()
{
  this._game = null;
  this._annotationMap = null;
  
  var elem = this._annotationElement;

  if (elem != null)
  {
    // Clear all content
    while(elem.firstChild)
    {
      elem.removeChild(elem.firstChild);
    }
  }
}

/*
  Creates annotation view for the specified game of pgn document.
*/
Annotation.prototype._create = function()
{
  this._clear();
  
  var elem = this._annotationElement;
  
  if (elem == null)
  {
    return;
  }

  var document = elem.ownerDocument;
  
  if (this._document == null)
  {
    return;
  }
  
  var game = this._document.games[this._gameIndex] ;

  if (game == null)
  {
    return;
  }

  this._game = game;
  this._activeMove = null;
  this._moveElement = null;
  this._annotationMap = new Object;

  var hasHeader = false;

  // Create heads.
  if (game.tags.White && (game.tags.White != "?") && 
    game.tags.Black && (game.tags.Black != "?"))
  {
    var header = document.createElement("span");
    var white = game.tags.White;
    
    if (game.tags.WhiteElo && (game.tags.WhiteElo != "?"))
    {
      white += " (" + game.tags.WhiteElo + ")";
    }
    
    var black = game.tags.Black;
    
    if (game.tags.BlackElo && (game.tags.BlackElo != "?"))
    {
      black += " (" + game.tags.BlackElo + ")";
    }

    header.className = "annotation-header";
    header["unselectable"]="on";
    header.innerText = white + " - " + black;
    
    if (hasHeader)
    {
      var brElement = document.createElement("br");
      
      brElement["unselectable"]="on";
      elem.appendChild(brElement);
    }
    
    elem.appendChild(header);
    hasHeader = true;
  }
  
  if (game.tags.Event && (game.tags.Event != "?"))
  {
    var header = document.createElement("span");
    
    header.className = "annotation-header";
    header["unselectable"]="on";
    header.innerText = game.tags.Event;
  
    if (hasHeader)
    {
      var brElement = document.createElement("br");
      
      brElement["unselectable"]="on";
      elem.appendChild(brElement);
    }
  
    elem.appendChild(header);
    hasHeader = true;
  }
  
  if (game.tags.Date)
  {
    var dateString = String(game.tags.Date);
    var p = dateString.indexOf("?");
    
    if (p == 0)
    {
      dateString = null;
    }
    else if (p != -1)
    {
      dateString = dateString.substring(
        0, 
        dateString.charAt(p - 1) == "." ? p - 1 : p);
    }

    if (dateString)
    {
      var header = document.createElement("span");
      
      header.className = "annotation-header";
      header["unselectable"]="on";
      header.innerText = dateString;
      
      if (hasHeader)
      {
        var brElement = document.createElement("br");
        
        brElement["unselectable"]="on";
        elem.appendChild(brElement);
      }
      
      elem.appendChild(header);
      hasHeader = true;
    }
  }
  
  if (game.tags.Round && (game.tags.Round != "?"))
  {
    var header = document.createElement("span");
    
    header.className = "annotation-header";
    header["unselectable"]="on";
    header.innerText = "Round: " + game.tags.Round;
  
    if (hasHeader)
    {
      var brElement = document.createElement("br");
      
      brElement["unselectable"]="on";
      elem.appendChild(brElement);
    }
  
    elem.appendChild(header);
    hasHeader = true;
  }
  
  if (game.tags.Annotator && (game.tags.Annotator != "?"))
  {
    var header = document.createElement("span");
    
    header.className = "annotation-annotator";
    header["unselectable"]="on";
    header.innerText = "(" + game.tags.Annotator + ")";
  
    if (hasHeader)
    {
      var brElement = document.createElement("br");
      
      brElement["unselectable"]="on";
      elem.appendChild(brElement);
    }
  
    elem.appendChild(header);
    hasHeader = true;
  }
  
  if (game.comment)
  {
    var commentElement = document.createElement("span");
    
    commentElement["unselectable"]="on";
    commentElement.className = "annotation-comment";
    commentElement.innerHTML = game.comment;
  
    if (hasHeader)
    {
      var brElement = document.createElement("br");
      
      brElement["unselectable"]="on";
      elem.appendChild(brElement);
    }
  
    elem.appendChild(commentElement);
    hasHeader = true;
  }
  
  if (hasHeader)
  {
    var brElement = document.createElement("br");
    
    brElement["unselectable"]="on";
    elem.appendChild(brElement);
    brElement = document.createElement("br");
    brElement["unselectable"]="on";
    elem.appendChild(brElement);
  }

  this._createMoves(elem, game.moves);
  
  if (game.result && (game.result != "*"))
  {
    elem.appendChild(document.createTextNode(" " + game.result));
  }
  
  this._selectionChanged();
    
  return true;
}

// Creates annotation for array of moves
Annotation.prototype._createMoves = function(parent, moves)
{
  var document = parent.document;
  
  parent["unselectable"]="on";
  
  for(var i = 0, c = moves.length; i < c; i++)
  {
    var move = moves[i];
    var text = move.move;

    if (move.moveNumber)
    {
      text = String(move.moveNumber) + (move.whiteMove ? "." : "...") + text;
    }
    
    if (move.annotation)
    {
      function addAnnotation(annotation)
      {      
        switch(annotation)
        {
          case 1: 
          {
            text += "!"; 
            
            break;
          }
          case 2: 
          {
            text += "?"; 
            
            break;
          }
          case 3:
          {
           text += "!!"; 
           
           break;
          }
          case 4:
          {
           text += "??"; 
           
           break;
          }
          case 5:
          {
           text += "!?"; 
           
           break; 
          }
          case 6:
          {
            text += "?!"; 
            
            break;
          }
          case 8: 
          case 7: 
          case 9:
          {
            text += "□"; 
            
            break;
          }
          case 10: 
          case 11: 
          case 12: 
          {
            text += "="; 
            
            break;
          }
          case 13: 
          {
            text += "∞"; 
            
            break;
          }
          case 14: 
          {
            text += "+="; 
            
            break;
          }
          case 15: 
          {
            text += "=+"; 
            
            break;
          }
          case 16: 
          {
            text += "+/="; 
            
            break;
          }
          case 17: 
          {
            text += "-/+"; 
            
            break;
          }
          case 18: 
          {
            text += "+-"; 
            
            break;
          }
          case 19: 
          {
            text += "-+"; 
            
            break;
          }
          case 22: case 23: 
          {
            text += "Θ"; 
            
            break;
          }
          case 30: 
          case 31: 
          case 32: 
          case 33: 
          case 34: 
          case 35: 
          {
            text += "C"; 
            
            break;
          }
          case 36: 
          case 37: 
          case 38: 
          case 39: 
          {
            text += "↑"; 
            
            break;
          }
          case 40: 
          case 41: 
          {
            text += "→"; 
          
            break;
          }
          case 42: 
          case 43: 
          case 44: 
          case 45: 
          case 46: 
          case 47: 
          {
            text += "=/∞"; 
            
            break;
          }
          case 131: 
          case 132: 
          case 133: 
          case 134: 
          case 135: 
          {
            text += "↔"; 
            
            break;
          }
          case 142:
          {
            text = "Ω " + text;
            
            break;
          }
          case 146:
          {
            text += " N";
            
            break;
          }
        }
      }
      
      if (move.annotation instanceof Array)
      {
        for(var annotationIndex = 0; 
          annotationIndex < move.annotation.length; 
          ++annotationIndex)
        {
          addAnnotation(move.annotation[annotationIndex]);
        }
      }
      else
      {
        addAnnotation(move.annotation);
      }
    }
    
    var moveElement = document.createElement("a");
    var self = this;
    
    moveElement.href = "javascript:";
    moveElement.attachEvent(
      "onclick", 
      function() { self._doClick(event); });
    moveElement["unselectable"]="on";
    moveElement.className = "annotation-move";
    moveElement["move-id"] = move.id;
    this._annotationMap[move.id] = moveElement.uniqueID;
    moveElement.innerHTML = text;
    parent.appendChild(moveElement);
    
    if (move.comment)
    {
      var commentElement = document.createElement("span");
      
      commentElement["unselectable"]="on";
      commentElement.className = "annotation-comment";
      commentElement.innerHTML = move.comment;
      parent.appendChild(document.createTextNode(" "));
      parent.appendChild(commentElement);
    }
    
    parent.appendChild(document.createTextNode(" "));
    
    var variations = move.variations;
    
    if (variations)
    {
      var variationsElement = document.createElement("span");
      
      variationsElement["unselectable"]="on";
      parent.appendChild(variationsElement);
      
      for(var j = 0, l = variations.length; j < l; j++)
      {
        var variationsCollapsed = document.createElement("a");
        
        variationsCollapsed.href = "javascript:";
        variationsCollapsed.attachEvent(
          "onclick", 
          function() { self._doClick(event); });
        variationsCollapsed.className = "annotation-variation-head";
        variationsCollapsed.innerText = "\xa0+\xa0...";
        variationsCollapsed["unselectable"]="on";
        variationsCollapsed.title = variations[j][0].comment ?
          variations[j][0].comment : "variation";
        variationsElement.appendChild(variationsCollapsed);
        
        var variationsExpanded = document.createElement("span");
        
        variationsExpanded.className = "annotation-variation" + (j % 3 + 1);
        variationsExpanded.style.display = "none";
        variationsExpanded["unselectable"]="on";
        variationsElement.appendChild(variationsExpanded);
        variationsElement.appendChild(document.createTextNode(" "));
        this._createMoves(variationsExpanded, variations[j]);
      }
    }
  }
}

Annotation.prototype._doClick = function(eventObj)
{
  var elem = this._annotationElement;
  
  if (!elem)
  {
    return true;
  }

  var src = eventObj.srcElement;
  var id = src["move-id"];

  if (id)
  {
    this._selectAnnotation(src);
  }
  else if (src.className.indexOf("annotation-variation-head") != -1)
  {
    var content = src.nextSibling;

    if (content.currentStyle.display == "none")
    {
      src.innerText = "\xa0-\xa0";
      content.style.display = "block";
    }
    else
    {
      src.innerText = "\xa0+\xa0...";
      content.style.display = "none";
    }
  }
  
  return true;
}

Annotation.prototype._selectAnnotation = function(element)
{
  var elem = this._annotationElement;
  
  if (elem)
  {
    var id = element ? element.uniqueID : null;
    
    if (this._activeMove == id)
    {
      return true;
    }
      
    if (this._activeMove)
    {
      var activeElement = elem.document.getElementById(this._activeMove);
      
      // TODO: find better solution temporary
      activeElement.style.cssText = "";
    
      this._activeMove = null;
      this._moveElement = null;
    }

    if (element)
    {
      this._activeMove = element.uniqueID;
      this._moveElement = 
        this._game.document.getElementById(element["move-id"]);

      var activeElement = elem.document.getElementById(this._activeMove);

      if (activeElement != null)
      {
        // TODO: find better solution temporary
        activeElement.style.cssText = this._internalActiveMoveStyle;
        activeElement.scrollIntoView();
      }
    }
  }
  
  this._selectionChanged();

  return true;
}

Annotation.prototype._selectionChanged = function()
{
  if (this._board != null)
  {
    if (!this._updatingBoard)
    {
      this._updatingBoard = true;
      
      var self = this;
      
      function doUpdateBoard()
      {
        if (self._game == null)
        {
          return;
        }
        
        self._updatingBoard = false;
        
        self._board.position.Load(
          self._moveElement ? 
            self._moveElement.getState() : 
            self._game.getState());
      }
      
      Util.run(doUpdateBoard, 0);
    }
  }
  
  if (this.onselectmove)
  {
    this.onselectmove();
  }
}

Annotation.prototype._findAnnotation = function(move)
{
  if (!move)
  {
    return null;
  }
    
  var id = this._annotationMap[move.id];
  
  if (!id)
  {
    return null;
  }
    
  return document.getElementById(id);
}


