﻿function SvgToString() {
    this.svgString = "";
    this.moveTo =
    function (x, y) {
        this.svgString = this.svgString + "M" + x + "," + y;
        return this;
    }
    this.curveTo =
    function (x1, y1, x2, y2, x, y) {
        this.svgString = this.svgString + "C" + x1 + "," + y1 + "," +
            x2 + "," + y2 + "," + x + "," + y;
        return this;
    }
    this.lineTo =
    function (x, y) {
        this.svgString = this.svgString + "L" + x + "," + y;
        return this;
    }

    return this;
}

function BoardMarkers(boardWrapper) {
    this.markers = [];

    var letter = [];
    letter["a"] = 1;
    letter["b"] = 2;
    letter["c"] = 3;
    letter["d"] = 4;
    letter["e"] = 5;
    letter["f"] = 6;
    letter["g"] = 7;
    letter["h"] = 8;

    var colors = [];
    colors['A'] = '#f00';
    colors['D'] = '#0f0';
    colors['I'] = '#ff0';
    colors['C'] = '#00f';

    var opacities = [];
    opacities['N'] = 0.6;
    opacities['L'] = 0.6;
    opacities['E'] = 0.4;
    opacities['H'] = 0.3;
    opacities['H'] = 0.1;

    var squareSize = boardWrapper.squareSize;

    var lastMarkers;

    var canvas = null;

    this.getCanvas = function () {
        if (canvas == null) {
            
            var brdMarker = boardWrapper.markersView;
            var board = boardWrapper.boardTable;
            canvas = Raphael(brdMarker, boardWrapper.visibleCols * squareSize, boardWrapper.visibleRows * squareSize);
        }        
        return canvas;
    }

    this.calculatePos =
    function (x, y) {

        if (boardWrapper.gui.flipped) {
            x = 9 - x
            y = 9 - y;
        }

        if (boardWrapper.isBoardrect) {
            x -= letter[boardWrapper.startX] - 1;
            y -= 8 - boardWrapper.finishY;
        }

        return { x: (x - 0.5) * (squareSize), y: (y - 0.5) * (squareSize) };

    }

    this.drawPoint =
     function (pointX, pointY, color, opacity) {
         var x = letter[pointX];
         var y = 9 - pointY;
         CirclePos = this.calculatePos(x, y);
         isSmall = boardWrapper.className.indexOf("small") != -1;
         var circRad;
         if (isSmall)
             circRad = 5;
         else
             circRad = 10;
         var markerPoint = this.getCanvas().circle(CirclePos.x, CirclePos.y, circRad);
         markerPoint.attr({ fill: color, stroke: "#000", opacity: opacity });
         this.markers.push(markerPoint);

     }

     this.drawCircle =
     function (pointX, pointY, color, opacity) {
         var x = letter[pointX];
         var y = 9 - pointY;
         CirclePos = this.calculatePos(x, y);
         var isSmall = boardWrapper.className.indexOf("small") != -1;
         var circRad = squareSize / 2;
         if (isSmall)
             opacWidth = 3;
         else
             opacWidth = 4;
         var markerPoint = this.getCanvas().circle(CirclePos.x, CirclePos.y, circRad - opacWidth / 2);
         markerPoint.attr({
             stroke: color,
             opacity: 1,
             "stroke-width": opacWidth,
             "stroke-opacity": opacity
         });

         this.markers.push(markerPoint);

     }

     this.drawSolidRectangle =
     function (pointX, pointY, color, opacity) {
         var x = letter[pointX];
         var y = 9 - pointY;
         if (boardWrapper.gui.flipped) {
             x = 9 - x
             y = 9 - y;
         }
         if (boardWrapper.isBoardrect) {
             x -= letter[boardWrapper.startX] - 1;
             y -= 8 - boardWrapper.finishY;
         }
         RecPos = { x: (x) * (squareSize), y: (y) * (squareSize) };
         var isSmall = boardWrapper.className.indexOf("small") != -1;

         if (isSmall)
             rectRad = 3;
         else
             rectRad = 4;

         if (isSmall)
             opacWidth = 3;
         else
             opacWidth = 4;
         var markerRect = this.getCanvas().rect(RecPos.x, RecPos.y, squareSize, squareSize - opacWidth / 2, rectRad);
         markerRect.attr({
             opacity: opacity,
             color: color             
         });

         this.markers.push(markerRect);

     }

     this.drawRectangle =
     function (pointX, pointY, color, opacity) {
         var x = letter[pointX];
         var y = 9 - pointY;
         if (boardWrapper.gui.flipped) {
             x = 9 - x
             y = 9 - y;
         }
         if (boardWrapper.isBoardrect) {
             x -= letter[boardWrapper.startX] - 1;
             y -= 8 - boardWrapper.finishY;             
         }
         RecPos = { x: (x - 1) * (squareSize), y: (y - 1) * (squareSize) };
         var isSmall = boardWrapper.className.indexOf("small") != -1;

         if (isSmall)
             rectRad = 3;
         else
             rectRad = 4;

         if (isSmall)
             opacWidth = 3;
         else
             opacWidth = 4;
         var markerRect = this.getCanvas().rect(RecPos.x, RecPos.y, squareSize - opacWidth / 2, squareSize - opacWidth / 2, rectRad);
         markerRect.attr({             
             stroke: color,
             opacity: 1,
             "stroke-width": opacWidth,
             "stroke-opacity": opacity
         });

         this.markers.push(markerRect);

     }

     this.drawText =
      function (fromX, fromY, toX, toY, opacity, text) {
          var fX = letter[fromX];
          var fY = 9 - fromY;
          var tX = letter[toX];
          var tY = 9 - toY;
          if (boardWrapper.gui.flipped) {
              fX = 9 - fX;
              fY = 9 - fY
              tX = 9 - tX;
              tY = 9 - tY
          }

          if (boardWrapper.isBoardrect) {
              fX -= letter[boardWrapper.startX] - 1;
              fY -= 8 - boardWrapper.finishY;
              tX -= letter[boardWrapper.startX] - 1;
              tY -= 8 - boardWrapper.finishY;

          }
          isSmall = boardWrapper.className.indexOf("small") != -1;
          var fontSize;
          if (isSmall)
              fontSize = "15";
          else
              fontSize = "30";
          fX = (fX - 0.5) * (squareSize);
          fY = (fY - 0.5) * (squareSize);
          tX = (tX - 0.5) * (squareSize);
          tY = (tY - 0.5) * (squareSize);

          var markerText = this.getCanvas().text(fX + parseInt(fontSize) - 3, fY,
                text).attr({ "font-size": fontSize, "fill": "#fff" });
          this.markers.push(markerText);
      }

     this.drawArrow =
	function (fromX, fromY, toX, toY, rounded, color, opacity) {
	    var fX = letter[fromX];
	    var fY = 9 - fromY;
	    var tX = letter[toX];
	    var tY = 9 - toY;
	    if (boardWrapper.gui.flipped) {
	        fX = 9 - fX;
	        fY = 9 - fY
	        tX = 9 - tX;
	        tY = 9 - tY
	    }

	    if (boardWrapper.isBoardrect) {
	        fX -= letter[boardWrapper.startX] - 1;
	        fY -= 8 - boardWrapper.finishY;
	        tX -= letter[boardWrapper.startX] - 1;
	        tY -= 8 - boardWrapper.finishY;

	    }

	    isSmall = boardWrapper.className.indexOf("small") != -1;

	    //размеры стрелки
	    if (isSmall) {
	        arrowX = 3;
	        arrowY = 8;
	        arrowZ = 10;

	    } else {
	        arrowX = 5;
	        arrowY = 15;
	        arrowZ = 20;

	    }

	    fX = (fX - 0.5) * (squareSize);
	    fY = (fY - 0.5) * (squareSize);
	    tX = (tX - 0.5) * (squareSize);
	    tY = (tY - 0.5) * (squareSize);

	    var lX = Math.abs(tX - fX);
	    var lY = Math.abs(tY - fY);
	    var tL = Math.sqrt(lX * lX + lY * lY);
	    var mod = -1 * lX / (tX - fX);
	    var rotationAngle;
	    if (lX == 0) {
	        rotationAngle = 0;
	    } else {
	        rotationAngle = -Math.atan((tX - fX) / (tY - fY));
	    }

	    if (lY == 0) {
	        rotationAngle = -rotationAngle;
	    } else if (tY > fY) {
	        rotationAngle = Math.PI + rotationAngle;
	    }

	    rotationAngle = rotationAngle / Math.PI * 180;
	    var markerArrow;

	    try {
	        if (rounded) {
	            var sq = Math.sqrt(squareSize * squareSize / 2);
	            var ArrowSVG = SvgToString();
	            ArrowSVG.moveTo(fX, fY).curveTo(fX - 2 + 0.5 * mod * sq, fY - sq, fX - arrowX + mod * sq, fY - 1.5 * sq, fX - arrowX + mod * sq, fY - 3 * sq + arrowY).lineTo(fX - arrowY + mod * sq, fY - 3 * sq + arrowZ).lineTo(fX + mod * sq, fY - 3 * sq).lineTo(fX + arrowY + mod * sq, fY - 3 * sq + arrowZ).lineTo(fX + arrowX + mod * sq, fY - 3 * sq + arrowY).curveTo(fX + arrowX + mod * sq, fY - 1.5 * sq, fX + 2 + 0.5 * mod * sq, fY - sq, fX, fY);
	            markerArrow = this.getCanvas().path(ArrowSVG.svgString);
	            markerArrow.attr({ fill: color, stroke: "#000", opacity: opacity });
	            var knightAngle = Math.atan(1 / 3) / Math.PI * 180;
	            markerArrow.rotate(rotationAngle - mod * knightAngle, fX, fY);
	        } else {
	            var ArrowSVG = SvgToString();
	            ArrowSVG.moveTo(fX, fY).lineTo(fX - arrowX, fY - tL + arrowY).lineTo(fX - arrowY, fY - tL + arrowZ).lineTo(fX, fY - tL).lineTo(fX + arrowY, fY - tL + arrowZ).lineTo(fX + arrowX, fY - tL + arrowY).lineTo(fX, fY);
	            markerArrow = this.getCanvas().path(ArrowSVG.svgString);
	            markerArrow.attr({ fill: color, stroke: "#000", opacity: opacity });
	            markerArrow.rotate(rotationAngle, fX, fY);
	        }
	    }
	    catch (e) {
	    }

	    this.markers.push(markerArrow);
	}

	this.drawMarkerArrow =
     function (marker) {         
         var opacity = opacities[marker.charAt(0)];
         var color = colors[marker.charAt(1)];
         fromX = marker.charAt(2);
         fromY = marker.charAt(3);
         toX = marker.charAt(4);
         toY = marker.charAt(5);
         rounded = false;
         this.drawArrow(fromX, fromY, toX, toY, rounded, color, opacity);
     }

     this.drawMarkerSquare =
      function(marker){
        var opacity = opacities[marker.charAt(0)];
        var color = colors[marker.charAt(1)];
        x = marker.charAt(2);
        y = marker.charAt(3);
        if ((marker.length == 6) && (marker.charAt(5) == '1'))
            this.drawRectangle(x, y, color, opacity);
        else
            this.drawCircle(x, y, color, opacity);
    }

    this.drawMarkerRectangle =
      function (marker) {
          var opacity = opacities[marker.charAt(0)];
          var color = colors[marker.charAt(1)];
          x = marker.charAt(2);
          y = marker.charAt(3);
          this.drawRectangle(x, y, color, opacity);
      }

      this.drawMarkerText =
       function (marker) {
           var opacity = opacities[marker.charAt(0)];
           fromX = marker.charAt(1);
           fromY = marker.charAt(2);
           toX = marker.charAt(3);
           toY = marker.charAt(4);
           var pos = marker.indexOf("'") + 1;
           this.drawText(fromX, fromY, toX, toY, opacity, marker.substr(pos, marker.length - 2));
       }


     this.drawMarkerNotText =
     function (marker) {         
         switch (marker.charAt(0)) {
             case 'A':                 
                 this.drawMarkerArrow(marker.substr(1));
                 break;
             case 'S':
                 this.drawMarkerSquare(marker.substr(1));
                 break;
             case 'R':
                 this.drawMarkerRectangle(marker.substr(1));
                 break;             
             default:
                 break;
         }
     }

     this.drawMarkerOnlyText =
     function (marker) {
         switch (marker.charAt(0)) {             
             case 'T':
                 this.drawMarkerText(marker.substr(1));
                 break;
             default:
                 break;
         }
     }

    this.clearMarkers =
     function () {         
         for (marker in this.markers)
             this.markers[marker].remove();
         this.markers = [];
     }

    this.notaDrawArrow =
     function (fromX, fromY, toX, toY, knight) {
        this.clearMarkers();
        var color = colors['I'];
        var opacity = opacities['L'];
        this.drawArrow(fromX, fromY, toX, toY, knight, color, opacity);
        this.drawPoint(fromX, fromY, color, opacity);
    }

    this.drawMarkers =
     function (markersString) {
         this.clearMarkers();
         lastMarkers = markersString;
         if (markersString)
             markers = markersString.split(' ');
         else
             markers = [];

         for (var marker in markers) {
             this.drawMarkerNotText(markers[marker]);
         }
         for (var marker in markers) {
             this.drawMarkerOnlyText(markers[marker]);
         }

     }

     this.redrawMarkers =
      function () {
          this.drawMarkers(lastMarkers);
      }
}
