$.extend($s,{

  drawing: {
    CANVAS_BACKGROUND: "thebackground",
    CANVAS_EDITABLE: "thecanvas",
    CANVAS_TEMPORARY: "theoverlay",
    
    MODE_BRUSH: 0,
    MODE_LINES: 1,
    MODE_RECTANGLES: 2,
    MODE_ELLIPSES: 3,
    currentMode: 0,
    
    CANVAS_HEIGHT: 328,
    CANVAS_WIDTH: 318,
    
    isDrawing: false,
    currentX: -1,
    currentY: -1,
    lastX: -1,
    lastY: -1,
    canvasX: -1,
    canvasY: -1,
    drawColor: "#ff0000",
    wallId: null,
    history: [],
    brushPath: [],
    
    renderHistory: function() {
      for(var a=0; a<this.history.length; a++) {
        this.renderSpecific(this.history[a]);
      }  
    },
    
    renderLast: function() {
      this.renderSpecific(this.history[this.history.length-1]);
    },
    
    renderSpecific: function(el) {
      if(el && el.hasOwnProperty('t')) {
        var c = $s.drawing.CANVAS_EDITABLE;
        switch(el.t) {
          case $s.drawing.MODE_BRUSH:
            $s.drawing.brush(c, el.p, el.c);
            break;
          case $s.drawing.MODE_LINES:
            $s.drawing.line(c, el.b[0], el.b[1], el.a[0], el.a[1], el.c);
            break;
          case $s.drawing.MODE_RECTANGLES:
            $s.drawing.rectangle(c, el.b[0], el.b[1], el.a[0], el.a[1], el.c);
            break;
          case $s.drawing.MODE_ELLIPSES:
            $s.drawing.ellipse(c, el.b[0], el.b[1], el.a[0], el.a[1], el.c);
            break;
        }
      }
    },
    
    undo: function() {
      $s.drawing.clearEditable();
      $s.drawing.history.pop();
      $s.drawing.renderHistory();
    },
    
    addRender: function(el) {
      this.history.push(el);
      this.clearOverlay();  
      this.renderHistory(); 
    },
    
    setMode: function(newMode) {
      $s.drawing.currentMode = parseInt(newMode);
      this.toggleMenu();
    }, 
    
    toggleMenu: function() {
      var newMode = $s.drawing.currentMode;
      $('.brush').attr("class", "brush" + (newMode == this.MODE_BRUSH ? " selected" : ""));
      $('.lines').attr("class", "lines" + (newMode == this.MODE_LINES ? " selected" : ""));
      $('.rectangles').attr("class", "rectangles" + (newMode == this.MODE_RECTANGLES ? " selected" : ""));
      $('.ellipses').attr("class", "ellipses" + (newMode == this.MODE_ELLIPSES ? " selected" : ""));
    },
    
    init: function() {
      this.reset();
      var ref= this;
      $().mousemove(function(e){
        ref.mouseMoved(e.pageX,e.pageY);
      }); 
    },
    
    reset: function() {
      this.drawColor= "#ff0000";
      this.currentMode = 0;
    },
    
    mouseMoved: function(newX, newY) {
      $s.drawing.lastX = newX;
      $s.drawing.lastY = newY;
      if(this.isDrawing) {
        switch(this.currentMode) {
          case this.MODE_BRUSH:
            this.brushTo($s.drawing.CANVAS_TEMPORARY, newX, newY);
            break;
          case this.MODE_LINES:
            this.lineTo($s.drawing.CANVAS_TEMPORARY, newX, newY);
            break;
          case this.MODE_RECTANGLES:
            this.rectangleTo($s.drawing.CANVAS_TEMPORARY, newX, newY);
            break;   
          case this.MODE_ELLIPSES:
            this.ellipseTo($s.drawing.CANVAS_TEMPORARY, newX, newY);
            break;   
        }
      }
    },
    
    setId: function(newId) {
      this.wallId = newId;
    },
    
    getId: function() {
      return this.wallId;
    },
    
    commitOverlay: function(newX, newY) {
      if(this.isDrawing) {
        switch(this.currentMode) {
          case this.MODE_BRUSH:
            this.brushTo($s.drawing.CANVAS_EDITABLE, newX,newY);
            if($s.drawing.currentMode == $s.drawing.MODE_BRUSH && this.brushPath.length > 1) {
                this.addRender({
                  t: $s.drawing.MODE_BRUSH,
                  p: $s.drawing.brushPath,
                  c: $s.drawing.drawColor
                });      
            }
	    $s.drawing.brushPath = [];
            this.clearOverlay();
            break;
          case this.MODE_LINES:
            this.lineTo($s.drawing.CANVAS_EDITABLE, newX, newY);
            this.clearOverlay();
            break;   
          case this.MODE_RECTANGLES:
            this.rectangleTo($s.drawing.CANVAS_EDITABLE, newX, newY);
            this.clearOverlay();
            break;   
          case this.MODE_ELLIPSES:
            this.ellipseTo($s.drawing.CANVAS_EDITABLE, newX, newY);
            this.clearOverlay();
            break;   
        }        
      }
    },
    
    enable: function() {
      this.history = [];
      this.brushPath = [];
      
      this.reset();
      var ref = this;
      $('#' + $s.drawing.CANVAS_TEMPORARY).mousedown(function(e){
        $s.drawing.mouseMoved(e.pageX,e.pageY);
        $s.drawing.start();
      });
      
      $('#' + $s.drawing.CANVAS_TEMPORARY).mouseup(function(e){        
        $s.drawing.commitOverlay(ref.lastX, ref.lastY);
        $s.drawing.stop();
      });
      
      $('#' + $s.drawing.CANVAS_TEMPORARY).each(function(){
        this.ontouchstart = function(){$s.drawing.start();};
        this.ontouchend = function(){
      	  $s.drawing.commitOverlay(ref.lastX, ref.lastY);
      	  $s.drawing.stop();
      	};       
        this.ontouchmove = function(e){
	       e.preventDefault();
          if(!e.hasOwnProperty('touches')) {
            return;
          }
          
          if(e.touches.length == 1){ // Only deal with one finger
            var touch = e.touches[0];
            $s.drawing.mouseMoved(touch.pageX,touch.pageY);
          }
        };
      });    
    },
    
    brushTo: function(el,newX,newY,startX,startY) {
      var oldX = this.currentX;
      var oldY = this.currentY;
      if(startX != null) {
        oldX = startX;
        oldY = startY;
      }
      this.currentX = newX - this.canvasX;
      this.currentY = newY - this.canvasY;
      if(oldX >= 0 && oldY >= 0) {
          if($s.drawing.brushPath.length == 0) {
            $s.drawing.brushPath.push([oldX,oldY]);
          }
          $s.drawing.brushPath.push([this.currentX, this.currentY]);
          $s.drawing.brush(el,[[oldX,oldY],[this.currentX, this.currentY]],$s.drawing.drawColor);   
      }    
    },
    
    brush: function(el, points, color) {
          var ctx = this.getContext(el);
          ctx.strokeStyle = color;
          ctx.lineWidth   = 4;                    
          ctx.beginPath();
          ctx.moveTo(points[0][0], points[0][1]);
          for(var a=1; a<points.length; a++) {
            ctx.lineTo(points[a][0], points[a][1]);
          }
          ctx.stroke();
    },
    
    lineTo: function(el,newX,newY,startX,startY) {
      var oldX = this.currentX;
      var oldY = this.currentY;
      if(startX != null) {
        oldX = startX;
        oldY = startY;
      }
      var wasNull = false;
      if(oldX == -1 || oldY == -1) {
        this.currentX = newX - this.canvasX;
        this.currentY = newY - this.canvasY;
      }else{
        if(el == $s.drawing.CANVAS_TEMPORARY) {
          this.clear($s.drawing.CANVAS_TEMPORARY);         
        }
        
        $s.drawing.line(el,newX,newY,oldX,oldY,$s.drawing.drawColor);
        
        if(el == $s.drawing.CANVAS_EDITABLE) {
        this.addRender({
            t: $s.drawing.MODE_LINES,
            a: [oldX, oldY],
            b: [newX, newY],
            c: $s.drawing.drawColor
          });     
        }
      }    
    },
    
    line: function(el,newX,newY,oldX,oldY,color) {
        var ctx = this.getContext(el);
        ctx.strokeStyle = color;
        ctx.lineWidth   = 4;                    
        ctx.beginPath();        
        ctx.moveTo(oldX, oldY);
        ctx.lineTo(newX, newY);
        ctx.stroke();           
    },
    
    rectangleTo: function(el,newX,newY,startX,startY) {
      var oldX = this.currentX;
      var oldY = this.currentY;
      if(startX != null) {
        oldX = startX;
        oldY = startY;
      }
      var wasNull = false;
      if(oldX == -1 || oldY == -1) {
        this.currentX = newX - this.canvasX;
        this.currentY = newY - this.canvasY;
      }else{
        if(el == $s.drawing.CANVAS_TEMPORARY) {
          this.clear($s.drawing.CANVAS_TEMPORARY);         
        }
    
        $s.drawing.rectangle(el,newX,newY,oldX,oldY,$s.drawing.drawColor);
        
        if(el == $s.drawing.CANVAS_EDITABLE) {
        this.addRender({
            t: $s.drawing.MODE_RECTANGLES,
            a: [oldX, oldY],
            b: [newX, newY],
            c: $s.drawing.drawColor
          }); 
        }
      }    
    },
    
    rectangle: function(el,newX,newY,oldX,oldY,color) {
        var ctx = this.getContext(el);
        ctx.fillStyle = color;
        ctx.beginPath();
        ctx.moveTo(oldX, oldY);        
        ctx.lineTo(oldX, newY);
        ctx.lineTo(newX, newY);
        ctx.lineTo(newX, oldY);
        ctx.lineTo(oldX, oldY);
        ctx.fill();       
    },
    
    ellipseTo: function(el,newX,newY,startX,startY) {
      var oldX = this.currentX;
      var oldY = this.currentY;
      if(startX != null) {
        oldX = startX;
        oldY = startY;
      }
      var wasNull = false;
      if(oldX == -1 || oldY == -1) {
        this.currentX = newX - this.canvasX;
        this.currentY = newY - this.canvasY;
      }else{
        if(el == $s.drawing.CANVAS_TEMPORARY) {
          this.clear($s.drawing.CANVAS_TEMPORARY);         
        }
        
        $s.drawing.ellipse(el,newX,newY,oldX,oldY,$s.drawing.drawColor);
        
        if(el == $s.drawing.CANVAS_EDITABLE) {
        this.addRender({
            t: $s.drawing.MODE_ELLIPSES,
            a: [minX, minY],
            b: [maxX, maxY],
            c: $s.drawing.drawColor
          });   
         }
      }    
    },
    
    ellipse: function(el,newX,newY,oldX,oldY,color) {
        //find the min and max X
        minX = maxX = minY = maxY = null;
        if(newX >= oldX) {
          maxX = newX;
          minX = oldX;
        }else{
          maxX = oldX;
          minX = newX;
        }
        if(newY >= oldY) {
          maxY = newY;
          minY = oldY;
        }else{
          maxY = oldY;
          minY = newY;
        }
        
        var ctx = this.getContext(el);
        ctx.fillStyle = color;
        ctx.fillEllipse(minX, minY, maxX-minX, maxY-minY); 
    },
    
    locate: function() {
      $s.drawing.canvasX = $('#' + $s.drawing.CANVAS_EDITABLE)[0].offsetLeft;
      $s.drawing.canvasY = $('#' + $s.drawing.CANVAS_EDITABLE)[0].offsetTop;
    },
    
    start: function(evt) {
      $s.drawing.locate();
      $s.drawing.isDrawing = true;
      $s.drawing.brushPath = [];
    },
    
    stop: function(evt) {
      $s.drawing.isDrawing = false;
      $s.drawing.currentX = -1;
      $s.drawing.currentY = -1;
      $s.drawing.lastX = -1;
      $s.drawing.lastY = -1;
    },
    
    clear: function(id) {
      $("#" + id)[0].getContext("2d").clearRect(0,0,this.CANVAS_WIDTH,this.CANVAS_HEIGHT);
    },
    
    clearOverlay: function() {
      this.clear($s.drawing.CANVAS_TEMPORARY);
    },
    
    clearEditable: function() {
      this.clearOverlay();
      this.clear($s.drawing.CANVAS_EDITABLE);
    },
    
    clearAll: function() {
      this.clearEditable();
      this.clear($s.drawing.CANVAS_BACKGROUND);
    },
    
    setColor: function(hex) {
      $s.drawing.drawColor = "#" + hex;
      $('#colorSelector div').css('backgroundColor', hex);
    },
    
    showPicker: function() {
      var ref = this;
      $('#colorSelector').ColorPicker({
        color: $s.drawing.drawColor,
        onShow: function (colpkr) {
          $(colpkr).fadeIn(500);
          $('#colorSelector').ColorPickerSetColor($s.drawing.drawColor);
          return false;
        },
        onHide: function (colpkr) {
          $(colpkr).fadeOut(500);
          return false;
        },
        onChange: function (hsb, hex, rgb) {
          $('#colorSelector div').css('backgroundColor', '#' + hex);
          $s.drawing.drawColor = '#' + hex;
        }
      });

    },
    
    loadImage: function(url, shouldClear, callback) {
      if(shouldClear != null && shouldClear) {
        this.clearAll();
      }
      
      var ctx = this.getContext();
      var img = new Image();
      img.onload = function() {
        ctx.drawImage(img, 0, 0);
        
        if(callback != null) {
          callback();
        }
      };
      img.src = url;
    },
    
    load: function(url, callback) {
      var img = new Image();
      var ref = this;
      img.onload = function() {
        ref.getContext($s.drawing.CANVAS_BACKGROUND).drawImage(img, 0, 0);
        if(callback != null) {
          callback();
        }
      }
      img.src = url;
    },
    
    toUrl: function() {
      var el = $('#' + $s.drawing.CANVAS_EDITABLE)[0];
      if(el.toDataURL) {
        return el.toDataURL("image/png");
      }else{
        $s.scroller.addMessage("null", "el doesnt have toDataURL", "okay");
      }
      return null;
    },
    
    save: function(callback) {
      var id = this.getId();
      var url = this.toUrl();
      var json = JSON.stringify($s.drawing.history);
      if(url) {
        $s.ajax.saveDrawingJson(id, json, callback);
      	//$s.ajax.saveDrawing(id, url, callback);
      }else{
	      //$s.scroller.addMessage('save', 'unable to save', 'okay');
      }
    },
    
    getContext: function(id) {
      return $('#' + id)[0].getContext("2d");
    }
  }

});
