
function RectMenu(width, heightPerItem, numItems, canvas) {
  this._left = 0;
  this._top = 0;
  this._numItems = numItems;
  this._width = width;
  this._heightPerItem = heightPerItem;
  this._ctx = canvas.getContext("2d");
  this._visible = false;
  this._lastChosen = null;
  this._oldSlice = null;
}
RectMenu.prototype = {
  onMouseDown: function( x, y ) {
    this._left = x;
    this._top = y;
    this._ctx.beginPath();
    this._ctx.moveTo(x, y);
    this._ctx.lineTo(x+ this._width, y);
    var bottom = y + this._numItems * this._heightPerItem;
    this._ctx.lineTo(x + this._width, bottom);
    this._ctx.lineTo(x, bottom);
    this._ctx.lineTo(x, y);
    this._ctx.stroke();

    this._ctx.mozTextStyle = "14pt sans serif";
    this._ctx.fillStyle = "black";

    for (var i = 0; i < this._numItems; i++) {
      this._ctx.beginPath();
      this._ctx.moveTo(x, y + i * this._heightPerItem);
      this._ctx.lineTo(x + this._width, y + i * this._heightPerItem);
      this._ctx.stroke();
      this._ctx.save();
      this._ctx.translate( x + (this._width / 2 ), y + (i + 0.5)* this._heightPerItem);
      this._ctx.mozDrawText(i);
      this._ctx.restore();
    }
    this._lastChosen = null;
    this._visible = true;
    this._oldSlice = null;
  },
  onMouseUp: function( x, y ) {
    redrawCanvas(this._ctx);
    this._lastChosen = this.getSliceNumFromPoint(x,y);
    this._visible = false;
  },
  onMouseMove: function( x, y ) {
    var slice = this.getSliceNumFromPoint(x, y);
    if (this._visible && slice != this._oldSlice) {
      if (this._oldSlice != null)
        this.fillSlice(this._oldSlice, "white");
      if (slice != null)
        this.fillSlice(slice, "red");
      this._oldSlice = slice;
    }    
  },
  getLastChosen: function() {
    return this._lastChosen;
  },
  getSliceNumFromPoint: function( x, y ) {
    if (x < this._left || x > this._left + this._width ) {
      return null;
    }
    if (y < this._top || y > this._top + this._heightPerItem * this._numItems ) {
      return null;
    }
    return Math.floor(( y - this._top ) / this._heightPerItem );
  },
  fillSlice: function( sliceNum, color ) {
    this._ctx.fillStyle = color;
    this._ctx.beginPath();
    this._ctx.moveTo(this._left, this._top + sliceNum * this._heightPerItem);
    this._ctx.lineTo(this._left + this._width, this._top+ sliceNum * this._heightPerItem);
    this._ctx.lineTo(this._left + this._width, this._top+ (sliceNum + 1) * this._heightPerItem);
    this._ctx.lineTo(this._left, this._top+ (sliceNum + 1) * this._heightPerItem);
    this._ctx.lineTo(this._left, this._top + sliceNum * this._heightPerItem);
    this._ctx.fill();
    this._ctx.stroke();
    this._ctx.save();
    this._ctx.mozTextStyle = "14pt sans serif";
    this._ctx.fillStyle = "black";
    this._ctx.translate( this._left + (this._width / 2 ), this._top + (sliceNum + 0.5)* this._heightPerItem);
    this._ctx.mozDrawText(sliceNum);
    this._ctx.restore();
  }
};


function PieMenu(innerRadius, outerRadius, numSpokes, canvas, subMenuSliceNum) {
  this._centerX = 0;
  this._centerY = 0;
  //this._optionsList = optionsList;
  this._numSpokes = numSpokes;
  this._innerRadius = innerRadius;
  this._outerRadius = outerRadius;
  this._visible = false;
  this._ctx = canvas.getContext("2d");
  this._lastChosen = null;
  this._oldSlice = null;
  this._subMenuSliceNum = subMenuSliceNum;
  this._subMenuVisible = false;
}
PieMenu.prototype = {
  onMouseDown: function( x, y ) {
    this.setCenter(x, y);
    this.draw();
    this._visible = true;
  },

  onMouseUp: function( x, y ) {
    this._lastChosen = this.getSliceNumFromPoint(x, y);
    redrawCanvas(this._ctx);
    this._oldSlice = null;
    this._visible = false;
  },
  onMouseMove: function( x, y ) {
    if (!this._visible) {
      return;
    }

    var slice = this.getSliceNumFromPoint(x, y);
    if (slice == this._subMenuSliceNum) {
      this.drawSubMenu();
      this._subMenuVisible = true;
    } else if (slice > this._numSpokes) {
      // mouse is in submenu
    } else if (this._subMenuVisible) {
      this.eraseSubMenu();
      this._subMenuVisible = false;
    }
    if (slice != this._oldSlice) {
      if (this._oldSlice != null)
        this.fillSlice(this._oldSlice, "white");
      if (slice != null)
        this.fillSlice(slice, "red");
      this._oldSlice = slice;
    }
  },
  getLastChosen: function() {
    return this._lastChosen;
  },
  setCenter: function( x, y ) {
    this._centerX = x;
    this._centerY = y;
  },
  moveToPolar: function( angle, distance ) {
    this._ctx.moveTo( this._centerX + distance * Math.cos(angle),
                      this._centerY + distance * Math.sin(angle) );
  },
  lineToPolar: function( angle, distance ) {
    this._ctx.lineTo( this._centerX + distance * Math.cos(angle),
                      this._centerY + distance * Math.sin(angle) );
  },
  renderTextPolar: function( angle, distance, text ) {
    this._ctx.mozTextStyle = "14pt sans serif";
    this._ctx.fillStyle = "black";
    this._ctx.save();
    this._ctx.translate(this._centerX + distance * Math.cos(angle),
                     this._centerY + distance * Math.sin(angle));
    this._ctx.mozDrawText(text);
    this._ctx.restore();
  },
  draw: function() {
    this._ctx.beginPath();
    this._ctx.arc(this._centerX, this._centerY, this._outerRadius,0,Math.PI*2,false);
    this._ctx.stroke();
    this._ctx.beginPath();
    this._ctx.arc(this._centerX, this._centerY, this._innerRadius,0,Math.PI*2,false);
    this._ctx.stroke();

    // The spokes:
    var angle = - Math.PI/this._numSpokes - Math.PI/2;
    for (var theta = 0; theta < this._numSpokes; theta++) {
      this._ctx.beginPath();
      this.moveToPolar(angle, this._innerRadius );
      this.lineToPolar(angle, this._outerRadius );
      this._ctx.stroke();
      this.renderTextPolar( angle + Math.PI/this._numSpokes, this._outerRadius * 3/4, 
                            (this._subMenuSliceNum == theta)?"Etc...":theta);
      angle += Math.PI * 2 / this._numSpokes;
    }
  },

  drawSubMenu: function() {
    var angleOfSlice = Math.PI*2 / this._numSpokes;

    var startAngle = this._subMenuSliceNum * angleOfSlice - Math.PI/4 - Math.PI/2;
    var endAngle = this._subMenuSliceNum * angleOfSlice + Math.PI/4 - Math.PI/2;
    this._ctx.beginPath();
    this.moveToPolar(startAngle, this._outerRadius );
    this.lineToPolar(startAngle, this._outerRadius * 2 );
    this._ctx.arc(this._centerX, this._centerY, this._outerRadius * 2, startAngle, endAngle, false);
    this.lineToPolar(endAngle, this._outerRadius );
    this._ctx.stroke();

    for (var theta = 0; theta < 4; theta++ ) {
      this._ctx.beginPath();
      this.moveToPolar( startAngle + theta*Math.PI/8, this._outerRadius);
      this.lineToPolar( startAngle + theta*Math.PI/8, this._outerRadius*2);
      this._ctx.stroke();
      this.renderTextPolar( startAngle + theta*Math.PI/8 + Math.PI/16, this._outerRadius * 3/2, 
                            this._numSpokes + theta);
    }
  },

  eraseSubMenu: function() {
    var angleOfSlice = Math.PI*2 / this._numSpokes;

    var startAngle = this._subMenuSliceNum * angleOfSlice - Math.PI/4 -0.01 - Math.PI/2;
    var endAngle = this._subMenuSliceNum * angleOfSlice + Math.PI/4 + 0.01- Math.PI/2;
    this._ctx.beginPath();
    this.moveToPolar(startAngle, this._outerRadius );
    this.lineToPolar(startAngle, this._outerRadius * 2 + 2 );
    this._ctx.arc(this._centerX, this._centerY, this._outerRadius * 2 + 2 , startAngle, endAngle, false);
    this.lineToPolar(endAngle, this._outerRadius );
    this._ctx.arc(this._centerX, this._centerY, this._outerRadius, endAngle, startAngle, true);
    this._ctx.fillStyle = "white";
    this._ctx.fill();
  },

  getSliceNumFromPoint: function( x, y ) {
    var deltaX = x - this._centerX;
    var deltaY = y - this._centerY;
    var distance = Math.sqrt( deltaX * deltaX + deltaY * deltaY );
    if (distance < this._innerRadius)
      return null;

    var angle = Math.atan2( deltaX, -1 * deltaY );
     if (angle < 0 ) {
      angle += Math.PI * 2;
    }
    var sliceWidth = Math.PI * 2 / this._numSpokes;
    angle += sliceWidth/2

    if (distance > this._outerRadius && this._subMenuVisible) {
        return this._numSpokes + 1;
    }

    var sliceNum = Math.floor( angle  / sliceWidth );
    while (sliceNum >= this._numSpokes)
      sliceNum -= this._numSpokes;
    while (sliceNum < 0)
      sliceNum += this._numSpokes;
    return sliceNum;
  },

  fillSlice: function( sliceNum, color ) {
    this._ctx.fillStyle = color;
    var sliceWidth = Math.PI * 2 / this._numSpokes;

    if (sliceNum >= this._numSpokes) {
      // a sub-menu item
      var newAngleStart = this._subMenuSliceNum * sliceWidth - Math.PI/4 - Math.PI/2;
      var theta = sliceNum - this._numSpokes;
      this._ctx.beginPath();
      this.moveToPolar( newAngleStart + theta*Math.PI/8, this._outerRadius);
      this.lineToPolar( newAngleStart + theta*Math.PI/8, this._outerRadius*2);
      this._ctx.arc(this._centerX, this._centerY, this._outerRadius * 2, newAngleStart + theta*Math.PI/8, newAngleStart + (theta+1)*Math.PI/8, false);
      this.lineToPolar( newAngleStart + (theta + 1)*Math.PI/8, this._outerRadius*2);
      this._ctx.arc(this._centerX, this._centerY, this._outerRadius, newAngleStart + (theta+1)*Math.PI/8, newAngleStart + theta*Math.PI/8, true);
      this.lineToPolar( newAngleStart + theta*Math.PI/8, this._outerRadius);
      this._ctx.fill();
      this._ctx.stroke();
      this.renderTextPolar( newAngleStart + theta*Math.PI/8 + Math.PI/16, this._outerRadius * 3/2, 
                            sliceNum );
    } else {
     // a main-menu item


      var newAngleStart = sliceNum * sliceWidth - Math.PI/2 - sliceWidth/2;
      var newAngleEnd = sliceNum * sliceWidth - Math.PI/2 + sliceWidth/2;

      this._ctx.beginPath();
      this._ctx.arc(this._centerX, this._centerY, this._innerRadius, newAngleStart, newAngleEnd, false);
      this._ctx.arc(this._centerX, this._centerY, this._outerRadius, newAngleEnd, newAngleStart, true);
      this._ctx.fill();
      this._ctx.stroke();
      this.renderTextPolar( (newAngleStart + newAngleEnd)/2,
                             this._outerRadius * 3/4,
                             (sliceNum == this._subMenuSliceNum)?"Etc...":sliceNum );
    }
  }
};

function redrawCanvas(context) {
  context.clearRect(0, 0, 600, 600);
  context.beginPath();
  context.moveTo(1, 1);
  context.lineTo(599, 1);
  context.lineTo(599, 599);
  context.lineTo(1, 599);
  context.lineTo(1, 1);
  context.stroke();
}


function writeOnCanvas( message, canvas ) {
  var ctx = canvas.getContext("2d");
  redrawCanvas(ctx);
  ctx.mozTextStyle = "14pt sans serif";
  ctx.fillStyle = "black";
  ctx.save();
  ctx.translate(250, 250);
  ctx.mozDrawText(message);
  ctx.restore();
}
