var ImageItem = Class.create({
  CLASSDEF : {
      name:  'ImageItem',
      parent: Item
  },
  
  initialize: function ImgItem_initialize(id, cViewProcess, asset, options) {
    this.itemType = 0;
    this.itemTypeName = "Image";
    
    if(asset == null) {
      alert("Unable to get image " + options.aid);
      return;
      //asset = makePlaceholderAsset();
      //loadAssetIntoItem(options.aid, this)
    } 
    
    ImageItem.parentClass.constructor().call(this, id, cViewProcess, asset, options);
    
    //this.isWilcomEMB = true; for local testing....
    
    this.moveClickEvent = this.moveClick.bindAsEventListener(this);
    this.sizeUpClickEvent = this.sizeUpClick.bindAsEventListener(this);
    this.sizeDownClickEvent = this.sizeDownClick.bindAsEventListener(this);
    
    this.aspectClickEvent = this.aspectClick.bindAsEventListener(this);
    
    this.advClickEvent = this.advClick.bindAsEventListener(this);
    this.colorWayChangeEvent = this.colorWayChange.bindAsEventListener(this);
    
    this.centerHEvent = this.centerHClick.bindAsEventListener(this);
    this.centerVEvent = this.centerVClick.bindAsEventListener(this);
    this.centerEvent = this.centerClick.bindAsEventListener(this);
    
    this.workingAssetLoaded = false;
    
    if(options.c != null) {
      this.colors = options.c.split(":");
    } else {
      this.colors = null;
    }
    this.colorCount = (options.cc == null) ?  this.asset.defaultColorCount : options.cc ;
    
    this.transparentColor = options.tc;
    if(this.transparentColor==null) {
      this.transparentColor = "Transparent";
    }

    this.rotated = false;
    this.setName(asset.name);
    this.oldTabName = "effects";
    this.currentSingleEffect = null;
    this.effects = options.eff;
    if(this.effects == null) {
      this.effects = {};
    } else {
      for(var i=0;i < imageEffects.size; i++) {
        if(imageEffects[i][3].single) {
          if(this.effects[imageEffects[i][0]] != null) {
            this.currentSingleEffect = imageEffects[i];
            break;
          }
        }
      }
    }
    this.effectsToBeApplied = false;
    this.borderId = options.b;
    if(this.borderId==null) {
      this.borderId = 0;
    }
    
    var rw = this.width;
    var rh = this.height;
    if(this.options.rw != null && this.options.rh != null) {
      rh = parseFloat(this.options.rh);
      rw = parseFloat(this.options.rw);
    }
    var deg = options.rot == null ? 0 : parseFloat(options.rot);
    this.setReferenceRotation(deg, true, {w:rw, h:rh});
    
    this.digitize = false;
    this.splitColors = false;
    if(this.cViewProcess.productProcess.process.isWilcomEMB()) {
      this.stitchCount = options.stc;
      if((this.cViewProcess.productProcess.process.isWilcomEMB())&&(!this.isWilcomEMB && !this.isSavedDigitized)) {
        //its a digitized asset....
        
        
        this.splitColors = (options.spc == "1");
        if(!this.splitColors) {
          if(options.po == null) {
            this.percentOpaque = 1.0;
          } else {
            this.percentOpaque = parseFloat(options.po);
          }
        }
        
        this.digitize = true;
        this.digitizationFee = null; //options.dig_fee;
        
        this.digitizedAsset = d.cart.registerDigitizedAsset(this);
        var primary = this.digitizedAsset.primaryItem();
        if(primary != this) {
          //check if the primary is rotated and if so get the real width/height...
          if((primary.rotated)&&(primary.rotatedRef != null)) {
            var dims = primary.getRealDims();
            this.height = dims.h;
            this.width = dims.w;
          } else {
            this.height = primary.height;
            this.width = primary.width;
          }
          
          this.maintainAspect = primary.maintainAspect;
          
          if(!(options.l && options.t)) {
            var w = this.cViewProcess.productProcess.fullWidth;
            var h = this.cViewProcess.productProcess.fullHeight;
            this.top = (h - this.height) / 2;
            this.left = (w - this.width) / 2;
          }
          
          
          this.colors = primary.colors;
          this.colorCount = primary.colorCount
          this.transparentColor = primary.transparentColor;
          log("Set Details from primary digitization: w=" + this.width + ", h=" + this.height);
          this.setReferenceRotation(deg, true, {w:this.width, h:this.height});
        }
        
        this.refreshDigitizedAsset(DIG_EVENT_STARTUP);
        this.updateDigitizationCosts();
      } else {
        if(d.mode == DESIGNER_MODE_AMEND) {
          if(this.isSavedDigitized) {
            if((this.asset.imageType != 2)&&(this.asset.digitizedState < 3)) {
              //amending the order that ordered the digitization... lock the size...
              this.allowResize = false;
            }
          }
        }
        this.stitchCount = parseInt(this.stitchCount, 10);
        
      }
    }
    this.colorWay = options.cw;
    if(d.mode == DESIGNER_MODE_AMEND) {
      if(this.asset.hasCost()) {
          this.canModifyDesign = false;
      }
    }
    if(d.designerOptions.showImageDims()) {
      this.setFeature("dim", true);
    } else {
      this.setFeature("dim", false);
    }
    if(d.designerOptions.showImageAdvanced()) {
      this.setFeature("adv", true);
    } else {
      this.setFeature("adv", false);
    }
    
    
  },
  
  
  
  initialiseManagePane: function ImgItem_initialiseManagePane() {
    log("ImageItem.initialiseManagePane()");
    var self = this;
    ImageItem.parentClass.method("initialiseManagePane").call(this);
    // bind objects
    
    
    this.thumb = $("mp1_" + this.elId + "_img");
    if(this.thumb!=null) {
      var sizes = this.asset.scale(69, 69);
      setTransPng(this.thumb, this.asset.getSUrl(), parseInt(sizes.w, 10), parseInt(sizes.h, 10));
      //this.thumb.src = this.asset.getUrl();
      //this.thumb.width = parseInt(sizes.w, 10);
      //this.thumb.height = parseInt(sizes.h, 10);
    }
    this.moveButtons = [];
    for(var i=0; i < 9; i++) {
      var b = $("mp1_" + this.elId + "_move_" + i);
      Event.observe(b, "click", this.moveClickEvent);
      Event.observe(b, "dblclick", this.moveClickEvent);
      this.moveButtons.push(b);
    }
    //this.moveButton.style.cursor = "pointer";
    
    
    this.sizeDown = $("mp1_" + this.elId + "_sizedown");
    this.sizeDown.style.cursor = "pointer";
    Event.observe(this.sizeDown, "click", this.sizeDownClickEvent);
    Event.observe(this.sizeDown, "dblclick", this.sizeDownClickEvent);
    
    this.sizeUp = $("mp1_" + this.elId + "_sizeup");
    this.sizeUp.style.cursor = "pointer";
    Event.observe(this.sizeUp, "click", this.sizeUpClickEvent);
    Event.observe(this.sizeUp, "dblclick", this.sizeUpClickEvent);
    
    this.aspectEl = $("mp1_" + this.elId + "_ar");
    Event.observe(this.aspectEl, "click", this.aspectClickEvent);
    
    if(this.maintainAspect) {
      this.aspectEl.checked = true;
    }
    
    this.centerHEl = $("mp1_" + this.elId + "_center_h");
    Event.observe(this.centerHEl, "click", this.centerHEvent);    
    
    this.centerVEl = $("mp1_" + this.elId + "_center_v");
    Event.observe(this.centerVEl, "click", this.centerVEvent);
    
    this.centerEl = $("mp1_" + this.elId + "_center");
    Event.observe(this.centerEl, "click", this.centerEvent);
    
    this.rotateContainer = $("mp1_" + this.elId + "_rotate_container");
    this.rotateImg = $("mp1_" + this.elId + "_rotate");
    this.rotateImg.style.cursor = "pointer";
    this.rotateImgLeft = $("mp1_" + this.elId + "_rotate_l");
    this.rotateImgLeft.style.cursor = "pointer";
    this.rotateImgRight = $("mp1_" + this.elId + "_rotate_r");
    this.rotateImgRight.style.cursor = "pointer";
    
    this.rotateImgTxt = $("mp1_" + this.elId + "_rotate_t");
    
    this.rotateWidget = new  RotateWidget(this.rotateContainer, this.rotateImg, this.rotateImgLeft, this.rotateImgRight, this.rotateImgTxt, function(d) { self.rotationChanged(d); });
    
    if(this.options.rot) {
      this.rotateWidget.setValue(parseInt(this.options.rot, 10));
    }
    if(this.getRotation() != 0) {
      this.rotated = true;
      this.aspectEl.disabled = true;
    } else {
      this.rotated = false;
    }
    
    //this.qualitySlider = $("mp1_" + this.elId + "_q_sl");
    this.qualitySliderContainer= $("mp1_" + this.elId + "_q_c_a");
    
    //this.advButton = $("mp1_" + this.elId + "_adv");
    //this.advButton.style.cursor = "pointer";
    this.advLink = $("mp1_" + this.elId + "_adv_link");
    Event.observe(this.advLink, "click", this.advClickEvent);
    
    this.advTable = $("mp1_" + this.elId + "_advt");
    
    
    this.initColors();
    
    var tc = $("ic_effects_" + this.elId);
    if(tc != null) {
      tc.onclick = function() { 
        self.selectTab("effects", self.elId);
        return false; 
      };
    }
    tc = $("ic_border_" + this.elId);
    if(tc != null) {
      tc.onclick = function() { self.selectTab("border", self.elId); return false; };
    }
    
    
    
    if((this.itemType==0) &&(((this.isWilcomEMB)||(this.digitize)||(this.isSavedDigitized)))) {
      
      if(this.isWilcomEMB) {
        
        $("mp1_" + this.elId + "_trans_container").style.display="none";
        $("mp1_" + this.elId + "_color_row").style.display="none";
        
        this.colorwayEl = $("mp1_" + this.elId + "_colorway") ;
        if(this.asset.colorWays != null) {
          
          for(var i=0; i < this.asset.colorWays.length; i++) {
            var cw = this.asset.colorWays[i];
            addSelectOption(this.colorwayEl, cw, i, this.colorWay ); 
          }
          if(this.asset.colorWays.length > 1) {
            $("mp1_" + this.elId + "_colorways").style.display="";
          }
          Event.observe(this.colorwayEl, "change", this.colorWayChangeEvent) ;
        }
        $("mp1_" + this.elId + "_ratio_container").style.display="none";
      } else if(this.isSavedDigitized) {
        $("mp1_" + this.elId + "_trans_container").style.display="none";
        $("mp1_" + this.elId + "_color_row").style.display="none";
      } else if(!this.splitColors) {
        $("mp1_" + this.elId + "_trans_container").style.display="";
        $("mp1_" + this.elId + "_color_row").style.display="none";
      }
      $("mp1_" + this.elId + "_q_container").style.display="none";
      if (d.mode == DESIGNER_MODE_CONFIGURE) { 
        this.setFeature("effects_content", false);
      } else { 
        this.setFeature("adv", false);
        //$("mp1_" + this.elId + "_adv_link_container").style.display="none"; 
      }
      
      if(this.digitize) {
        this.updateDigitizationNotice(true);
        this.refreshDigitizedAsset(0);
      }
    }
    this.initFeature("size_arrows");
    this.initFeature("adv");
    if((this.itemType==0)&&(d.designerOptions.showImageAdvanced())&&(d.designerOptions.showImageAdvancedOpen())) {
      this.advClick();
    }
    //this.initEBPane();
  },
  
  initEBPane: function ImgItem_initEBPane() {
    var div = $("i_effects_list_" + this.elId);
    if(div!= null) {
      var html = '<ul>';
      for(var i=0;i< imageEffects.length;i++) {
        var effect = imageEffects[i];
       /* if((i>0)&&(i%2==0)) {
          cell = "</tr><tr>";
        } else {
          cell = "";
        }*/
        cell = '<li class="et_effect" align="center" valign="top" id="i_ef_' + this.elId + '_' + effect[0] + '" onmouseover="ieOMO(this);" onmouseout="ieOMOu(this);"  onclick="ieOMc(' + this.id + ',' + i + ');"><img src="/ppr/images/effects/' + effect[2] + '"/>';
        cell += "<label>"+effect[1]+"</label>";
        cell += '</li>';
        
        html += cell;
      }
      html += "";
      
      div.innerHTML = html;
      
      d.effectIconsLoaded = true;
    
      this.selectDefaultEffect(this.effects);
    
    }
  },
  
  initColors: function ImgItem_initColors() {
    var colors = this.asset.getColors(this.colorCount);
    var allowChangeColor = true;
    if(this.isSavedDigitized) {
      allowChangeColor = false;
    } else if(this.digitize) {
      if(this.digitizedAsset.primaryItem() != this) {
        allowChangeColor = false;
      }
    }
    var buttonClass = allowChangeColor ? "mp_color_button" : "mp_color_display"; 
    if(colors != null) {
      
      var tr = $("mp1_" + this.elId + "_colors");
      if(tr == null) {
        return;
      }
      if(this.colors == null) {
        this.colors = [];
      }
      var validColorCount = 0;
      for(var i=0;i<colors.length; i++) {
        var color =colors[i];
        if(color != null) {
          validColorCount ++;
          if(this.colors.length <= i) {
            this.colors.push(color);
          } else if((this.colors[i] == null)||(this.colors[i] == "")) {
            this.colors[i] = color;
          }
        }
      }
      if(this.colors.length > validColorCount) { //the locally defined colors is larger....it should equal assets color count...
        this.colors = this.colors.slice(0, validColorCount);
      }
      tr.innerHTML = "";
      for(var i=this.colors.length-1; i >=0; i--) {
        var color = this.colors[i];
        
        var td = document.createElement("LI");
        if(color == "Transparent") {
          td.innerHTML = '<div class="' + buttonClass + '" style="width:10px;display:inline;margin-right:2px;font-size:8px;height:10px;background-image: url(/ppr/images/trans-display-small.gif);"><img src="' + d.pathPrefix + '/images/trans.gif" width="10" height="10" border="0"/></div>';
        } else {
          td.innerHTML = '<div class="' + buttonClass + '" style="width:10px;display:inline;margin-right:2px;font-size:8px;height:10px;background-color:' + color + ';"><img src="' + d.pathPrefix + '/images/trans.gif" width="10" height="10" border="0"/></div>';
        }
        tr.appendChild(td);
        var div = td.firstChild;
        if(allowChangeColor) {
          div.onclick = new bindFunc({div: div, idx: i, item: this}, function(l) { 
            l.item.setColorClick(l.div, l.idx);
          });    
        }
      }
      $("mp1_" + this.elId + "_color_row").style.display="";
    } else {
      var tcont = $("mp1_" + this.elId + "_trans_container");
      if(tcont != null) {
        tcont.style.display="";
        this.transColorButton = $("mp1_" + this.elId + "_transparent_color");
        this.transColorButton.className = buttonClass;
        if(this.transparentColor=="Transparent") {
          this.transColorButton.style.backgroundColor = "";
          this.transColorButton.style.backgroundImage = "url(/ppr/images/trans-display-small.gif)";
        } else {
          this.transColorButton.style.backgroundColor = this.transparentColor;
          this.transColorButton.style.backgroundImage = "";
        }
      
        if(allowChangeColor) {
          var self = this;
          this.transColorButton.onclick =function() { 
            pwColorPicker.selectColor(null, self.transColorButton, this.transparentColor,  function(c) { self.colorCallback(c, self.transColorButton, -1); },{allow_transparency:true});
              
            //showColorPicker(self.transColorButton, function(c) { self.colorCallback(c, self.transColorButton, -1); }, true, "No Transparency");
          };
        }
      }
    }
  },
  
  setColorClick: function ImgItem_setColorClick(el, idx) {
    var self = this;
    var curColor = idx == -1 ? this.transparentColor : this.colors[idx];
    //showColorPicker(el, function(c) { self.colorCallback(c, el, idx); }, true);
    pwColorPicker.selectColor(this.cViewProcess.productProcess.id, el, curColor,  function(c) { self.colorCallback(c, el, idx); }, {allow_transparency:true});
  },
  
  colorWayChange: function ImgItem_colorWayChange(event){
    this.colorWay = this.colorwayEl.value ;
//    log(this.colorWay) ;
    this.updateImageSrc();
    this.setDirty();
  },
  
  colorCallback: function ImgItem_colorCallback(color, el, idx) {
    if(color=="Transparent") {
      el.style.backgroundColor = "";
      el.style.backgroundImage = "url(/ppr/images/trans-display-small.gif)";
    } else {
      el.style.backgroundColor = color;
      el.style.backgroundImage = "";
    }
    if(idx==-1) {
      this.transparentColor = color;
      if(this.digitize && !this.splitColors) {
        this.asset.getOpacity(color, function(percent) {
            this.percentOpaque = parseFloat(percent);
            this.updateDigitizationNotice(true,true);
        }.bind(this));
      }
    } else {
      this.colors[idx] = color;
    }
    this.updateImageSrc();
    this.setDirty();
    this.updateDigitizationNotice(true,true);
    if(this.digitizedAsset != null) {
      this.digitizedAsset.changed(this,DIG_EVENT_COLOR);
    }
    //d.itemChanged(true);
  },
  
  
  buildElement: function ImgItem_buildElement() {
    this.el = document.createElement("IMG");
    this.el.id = "d_" + this.elId;
    this.el.style.display = "none";
    this.el.style.position = "absolute";
	this.el.style.cursor="pointer";
    var deg = this.getRotation();
    if(deg==0) {
      setTransPng(this.el, this.asset.getUrl());
    } else {
      this.el.src = "/images/trans.gif"; //it looks crap when the image appears unrotated/oversize...
    }
    /*
    if(useAlphaHack) {
      this.el.src = d.pathPrefix + "/images/trans.gif";
      this.el.style.fontSize = "1px";
      //el.style.display="inline-block";
      this.el.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + this.asset.getUrl() + '", sizingMethod="scale")';
      //this.el.style.filter = 'progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand")\nprogid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + this.asset.url + '", sizingMethod="scale")';
    } else {
      this.el.src = this.asset.getUrl();
    }
    */
    this.cViewArea.canvas.appendChild(this.el);
    
    //var self = this;
    
    if((deg==0)&&(this.colors == null)) {
      this.asset.loadWorkingAsset(function() { 
        this.setSrc(this.asset.getWUrl());
        /*if(this.thumb != null) {
          setTransPng(this.thumb, this.asset.getWUrl());
          //self.thumb.src = self.asset.getWUrl();
        }*/
        log("loaded working asset");
      }.bind(this));
    } else {
      this.updateImageSrc();
      this.asset.loadWorkingAsset(function() { 
        /*if(this.thumb != null) {
          setTransPng(this.thumb, this.asset.getWUrl());
          //self.thumb.src = self.asset.getWUrl();
        }*/
        log("loaded working asset");
      }.bind(this));
    }
    
    this.el.style.zIndex = this.getElementZIndex();
    
    return this.el;
  },
  
  del: function ImgItem_del() {
    if(this.moveButtons != null) {
      for(var i=0; i < this.moveButtons.length; i++) {
        Event.stopObserving(this.moveButtons[i], "click", this.moveClickEvent);
        Event.stopObserving(this.moveButtons[i], "dblclick", this.moveClickEvent);
      }
      Event.stopObserving(this.sizeDown, "click", this.sizeDownClickEvent);
      Event.stopObserving(this.sizeDown, "dblclick", this.sizeDownClickEvent);
      Event.stopObserving(this.sizeUp, "click", this.sizeUpClickEvent);
      Event.stopObserving(this.sizeUp, "dblclick", this.sizeUpClickEvent);
      Event.stopObserving(this.aspectEl, "click", this.aspectClickEvent);
      if(this.colorwayEl != null) {
        Event.stopObserving(this.colorwayEl, "change", this.colorWayChangeEvent) ;
      }
      Event.stopObserving(this.centerHEl, "click", this.centerHEvent);    
      Event.stopObserving(this.centerVEl, "click", this.centerVEvent);
      Event.stopObserving(this.centerEl, "click", this.centerEvent);
      Event.stopObserving(this.advLink, "click", this.advClickEvent);
    } 
    if(this.rotateWidget!=null) {
      this.rotateWidget.del();
    }
    if(this.digitizedAsset != null) {
      this.digitizedAsset.removeItem(this);
    }
    ImageItem.parentClass.method("del").call(this);
  },
  
  setSrc: function ImgItem_setSrc(url, updateInfo) {
    var self = this;
    var rotCount = this.rotationCounter;
    var rotRef = this.rotatedRef;
    this.currentSrc = url;
    if(this.el==null) return;
    setTransparentImage(this.el, this.el, url, function() {
        if(self.itemType == 0) {
          self.translateRotated(rotCount, rotRef);
          self.checkPosition();
        }
        if(updateInfo != null) {
          if((useCroppedImageHack)&&(updateInfo.checkCropIssue == true)) {
            window.setTimeout( function() {
                var refreshJoin = "?";
                if(self.currentSrc.indexOf("?") != -1) {
                  refreshJoin = "&";
                }
                log("Resetting Src Because of useCroppedImageHack to " + self.currentSrc + refreshJoin + "refresh");
              $(self.el.id).src = self.currentSrc + refreshJoin + "refresh";
            }, 1000);
            
          }
        }
    });
  },
  
  getSrc: function ImgItem_getSrc() {
    return this.currentSrc;
  },
  
  select: function ImgItem_select(dontEnterCustomisePane, event) {
    ImageItem.parentClass.method("select").call(this, dontEnterCustomisePane,event);
  },
  
  moveClick: function ImgItem_moveClick(event) {
    Event.stop(event);
    var liEl = Event.findElement(event, "li");
    var deltaX = this.cViewProcess.productProcess.fullWidth / 20;
    var deltaY = this.cViewProcess.productProcess.fullHeight / 20;
    
    var vDelta = liEl.className.substr(0,1);
    var hDelta = liEl.className.substr(2,1);
    
    if(vDelta == "t") {
      this.top -= deltaY;
    } else if(vDelta == "b") {
      this.top += deltaY;
    }
    if(hDelta == "l") {
      this.left -= deltaX;
    } else if(hDelta == "r") {
      this.left += deltaX;
    }
    
    var newPositionType = this.getItemPositioning();
    
    if(newPositionType == 1) {
      log("outside!!!");
      this.del();
      return;
    }
      
      
    this.setPosition();
    if(this.selected) {
      this.autoRepositionHandles();
    }
    this.setDirty();
    
  },
  
  sizeUpClick: function ImgItem_sizeUpClick(event) {
    Event.stop(event);
    if(!this.allowResize) {
      return;
    }
    if((this.isWilcomEMB)||(this.isSavedDigitized)) {
      if(this.rotatedRef == null) {
        this.setReferenceRotation();
      }
      
      var hinc = this.rotatedRef.h / 50;
      var maxHeight = this.rotatedRef.h + (10 * hinc);
      if(this.height < maxHeight) {
        this.height += hinc;
        var winc = this.rotatedRef.w / 50;
        this.width += winc;
        this.left -= winc/2;
        this.top -= hinc/2;
      } else {
        log("max height (" + maxHeight + ") reached");
        return;
      }
    } else {
      var dX = this.width / 20;
      var dY = this.height / 20;
      
      this.width += dX;
      this.height += dY;
      this.left -= dX/2;
      this.top -= dY/2;
    }
    this.setPosition();
    if(this.selected) {
      this.autoRepositionHandles();
    }
    this.setDirty();
    //d.itemChanged(true);
    if(!this.checkQuality()) {
      d.showQualityWarning();
    }
  },
  
  sizeDownClick: function ImgItem_sizeDownClick(event) {
    Event.stop(event);
    if(!this.allowResize) {
      return;
    }
    if((this.isWilcomEMB)||(this.isSavedDigitized)) {
      if(this.rotatedRef == null) {
        this.setReferenceRotation();
      }
      
      var hinc = this.rotatedRef.h / 50;
      var minHeight = this.rotatedRef.h - (10 * hinc);
      if(this.height > minHeight) {
        this.height -= hinc;
        var winc = this.rotatedRef.w / 50;
        this.width -= winc;
        this.left += winc/2;
        this.top += hinc/2;
      } else {
        log("min height (" + minHeight + ") reached");
        return;
      }
    } else {
      var dX = this.width / 20;
      var dY = this.height / 20;
      
      this.width -= dX;
      this.height -= dY;
      this.left += dX/2;
      this.top += dY/2;
    }
    
  
    this.setPosition();
    if(this.selected) {
      this.autoRepositionHandles();
    }
    this.setDirty();
    //d.itemChanged(true);
    
  },
  
  aspectClick: function ImgItem_aspectClick(event) {
    this.maintainAspect = this.aspectEl.checked;
    if(this.maintainAspect) {
      var dims = d.toCanvasDims({w:this.width, h:this.height, l:this.left, t:this.top},this.cViewProcess.productProcess );
      this.setHeight(parseInt(dims.h, 10));
      var dims = d.fromCanvasDims(this.getDims(),this.cViewProcess.productProcess);
      this.width = dims.w;
      this.autoRepositionHandles();
    }
  },
  
  centerClick: function ImgItem_centerClick(event) {
    var w =  this.cViewProcess.productProcess.fullWidth;
    var h = this.cViewProcess.productProcess.fullHeight;
    this.top = (h - this.height) / 2;
    this.left = (w - this.width) / 2;
    this.setPosition();
    this.autoRepositionHandles();
    this.setDirty();
    Event.stop(event);
  },  
  
  centerVClick: function ImgItem_centerVClick(event) {
    var h = this.cViewProcess.productProcess.fullHeight;
    this.top = (h - this.height) / 2;
    this.setPosition();
    this.autoRepositionHandles();
    this.setDirty();
    Event.stop(event);
  },
  
  centerHClick: function ImgItem_centerHClick(event) {
    var w =  this.cViewProcess.productProcess.fullWidth;
    this.left = (w - this.width) / 2;
    this.setPosition();
    this.autoRepositionHandles();
    this.setDirty();
    Event.stop(event);
  },
  
  advClick: function ImgItem_advClick(event) {
    if(this.advTable.style.display=="none") {
      this.initAdvanced();
      this.advTable.style.display="";
	  this.advLink.className="alt";
      //this.advButton.src=d.pathPrefix + "/images/mp/arrow_up.gif";
    } else {
      this.advTable.style.display="none";
	  this.advLink.className=null;
      //this.advButton.src=d.pathPrefix + "/images/mp/arrow_down.gif";
    }
    if(event != null) Event.stop(event);
    return false;
  },
  
  initAdvanced: function ImgItem_initAdvanced() {
    if(!this.advancedInit) {
      this.initEBPane();
      this.advancedInit = true;
    }
  },
  
  rotationChanged: function ImgItem_rotationChanged(deg) {
    
    if(this.rDelay != null) {
      window.clearTimeout(this.rDelay);
    }
    if(this.rotationCounter==null) {
      this.rotationCounter = 1;
    } else {
      this.rotationCounter ++;
    }
    this.setReferenceRotation(deg);
  
    var x = this.left + this.width / 2;
    var y = this.top + this.height / 2;
    
    
    
    log("rotationChanged: w=" + this.rotatedRef.w + "(" + this.width + ")" + " ,h=" + this.rotatedRef.h + "(" + this.height + ") ,deg=" + this.rotatedRef.angle);
    
    this.width = this.rotatedRef.w;
    this.height = this.rotatedRef.h;
    this.left = x - this.rotatedRef.w/2;
    this.top = y - this.rotatedRef.h/2;
    
    //this.allowResize = false; //should this be commented out?
    this.removeHandles();
    this.addHandles();

    var self = this;
    this.rDelay = window.setTimeout( function() { 
      self.updateImageSrc();
      self.setDirty();
    }, 100);
    
    log(deg);
    if(deg != 0) {
      this.rotated = true;
      this.aspectEl.disabled = true;
    } else {
      this.rotated = false;
      this.aspectEl.disabled = this.lockedDigitization();
    }
    this.updateTitleSize();
    this.checkPosition();
  },
  
  setReferenceRotation: function ImgItem_setReferenceRotation(deg, ignoreFrom, passedDims) {
    var dims = {};
    if(passedDims != null) {
      dims = passedDims;
    } else if((this.rotatedRef != null)&&(ignoreFrom!=true)) {
      dims = this.fromRotatedDims({w: this.width, h:this.height}, this.rotatedRef.angle); //toRotatedDims needs the actual dims, not the bounding box..
      log("setReferenceRotation (from): w=" + dims.w + "(" + this.width + ")" + " ,h=" + dims.h + "(" + this.height + ") ,deg=" + this.rotatedRef.angle);
      
    } else {//first time called...TODO: handle loading rotated image...
      dims.w = this.width;
      dims.h = this.height;
      log("setReferenceRotation (init): w=" + dims.w + " ,h=" + dims.h);
    }
    this.rotatedRef = this.toRotatedDims(dims, deg);
    log("toRotatedDims: w=" + this.rotatedRef.w + " ,h=" + this.rotatedRef.h + " deg=" + deg);
    this.rotatedRef.a = parseFloat(this.rotatedRef.w) / parseFloat(this.rotatedRef.h);
  },
  
  translateRotated: function ImgItem_translateRotated(rotCount, rotatedRef) {   
    if(this.rotationCounter == rotCount) {
      if(rotatedRef != null) {
        var x = this.left + this.width / 2;
        var y = this.top + this.height / 2;
        
        this.width = rotatedRef.w;
        this.height = rotatedRef.h;
        this.left = x - this.rotatedRef.w/2;
        this.top = y - this.rotatedRef.h/2;
      }
      var dims = this.toCanvasDims(); 
      
      this.setHeight(parseInt(dims.h, 10));
      this.setWidth(parseInt(dims.w, 10));
      this.setTop(parseInt(dims.t, 10));
      this.setLeft(parseInt(dims.l, 10));
      //this.allowResize = true; //should this be commented out?
      if(this.selected) {
        this.removeHandles();
        this.addHandles();
      }
    }
    
  },
  
  //convert the size to the bounding box of the rotated dims
  toRotatedDims: function ImgItem_toRotatedDims(dims, angle) {
    var pi2 = Math.PI / 2.0;

    var oldWidth = parseFloat(dims.w);
    var oldHeight = parseFloat(dims.h);

    if(angle == null) {
      angle = parseFloat(this.getRotation());
    }
    // Convert degrees to radians
    var theta = angle * Math.PI / 180.0;
    var locked_theta = theta;

    // Ensure theta is now [0, 2pi)
    while (locked_theta < 0.0) {
      locked_theta += 2 * Math.PI;
    }

    
    var adjacentTop=0, oppositeTop=0;
    var adjacentBottom=0, oppositeBottom=0;

    // We need to calculate the sides of the triangles based
    // on how much rotation is being done to the bitmap.
    //   Refer to the first paragraph in the explaination above for 
    //   reasons why.
    if ((locked_theta >= 0.0 && locked_theta < pi2) || (locked_theta >= Math.PI && locked_theta < (Math.PI + pi2))) {
      adjacentTop = parseFloat(Math.abs(Math.cos(locked_theta))) * oldWidth;
      oppositeTop = parseFloat(Math.abs(Math.sin(locked_theta))) * oldWidth;

      adjacentBottom = parseFloat(Math.abs(Math.cos(locked_theta))) * oldHeight;
      oppositeBottom = parseFloat(Math.abs(Math.sin(locked_theta))) * oldHeight;
    } else {
      adjacentTop = parseFloat(Math.abs(Math.sin(locked_theta))) * oldHeight;
      oppositeTop = parseFloat(Math.abs(Math.cos(locked_theta))) * oldHeight;

      adjacentBottom = parseFloat(Math.abs(Math.sin(locked_theta))) * oldWidth;
      oppositeBottom = parseFloat(Math.abs(Math.cos(locked_theta))) * oldWidth;
    }

    var newWidth = adjacentTop + oppositeBottom;
    var newHeight = adjacentBottom + oppositeTop;

    
    return {w:newWidth, h:newHeight, rw:oldWidth, rh:oldHeight, angle:angle, oa:oldWidth/oldHeight  };
  },
  
  //convert the size from the bounding box to the rotated dims (uses hack).. assumes dims are in actual size (not canvas size)
  fromRotatedDims: function ImgItem_fromRotatedDims(dims, angle) {
    //compare the size between this.rotatedRef and size.. use ratio to determine final size..
    if(angle == null) {
      angle = parseFloat(this.getRotation());
    }
    if(this.rotatedRef == null) {
      this.setReferenceRotation(); //make a bounding box from the original asset size..
    }
    //compare ratio of heights...
    var ratio = parseFloat(this.rotatedRef.h) / parseFloat(dims.h);
    return {h: this.rotatedRef.rh / ratio, w: this.rotatedRef.rw / ratio};
    //this.height = this.asset.height / ratio;
    //this.width = this.asset.width / ratio;
  },
  
  //calls above using current dims to get non rotated dims of the object..
  getRealDims: function ImgItem_getRealDims() {
    return this.fromRotatedDims({w:this.width, h:this.height});;
  },
  
  updateImageSrc: function ImgItem_updateImageSrc() {
    var deg = this.getRotation();
    if((deg==0)&&(this.colors == null)&&(!this.hasEffects())&&(this.borderId==0)&&(this.transparentColor=="Transparent")) {
      var url = this.asset.getWUrl() ;
      if (this.colorWay){
        log("*** Colorways") ;
        log(this.asset.colorWays) ;
        var cw_i = this.colorWay ;
        if(cw_i > 0) url = url.replace(/thumb300/, "colorway-"+cw_i) ;
      }
      this.setSrc(url);
    } else {
      var oa = (this.rotatedRef == null)? 0 : this.rotatedRef.oa;
      
      var cw_t = this.colorWay ? "&cw="+this.colorWay : "" ;
      
      var url = d.pathPrefix + "/designer/get_image?id=" + this.asset.id + this.getColorParam() + "&deg=" + deg + "&bid=" + this.borderId + 
        "&tc=" + encodeURIComponent(this.getIeSafeColorParam(this.transparentColor)) +cw_t+
        "&" + this.serialiseState("es", this.getWorkingState()).join('&') +"&oa=" + encodeURIComponent(oa);
      this.setSrc(url);
      
      //var colors = this.getColorParam();
      //this.setSrc(d.pathPrefix + "/designer/rotate_image?id=" + this.asset.id + "&deg=" + deg + colors);
      
    }
  },
  
  getColorParam: function ImgItem_getColorParam() {
    var colors = "";
    if(this.colors != null) {
      colors = "&colors=";
      for(var i=0;i<this.colors.length;i++) {
        if(i != 0) {
          colors +=encodeURIComponent(":");
        }
        colors += encodeURIComponent(this.getIeSafeColorParam(this.colors[i]));
      }
      colors += "&cc=" + this.colorCount;
    }
    return colors;
  },
  
  getIeSafeColorParam: function ImgItem_getIeSafeColorParam(color) {       
    if((color == null)||(color == "")) {
        return "";
    }
    if(color.substr(0, 1) == "#") {
      return color.substr(1, 6);
    }
    return color;
  },
  
  setHeight: function ImgItem_setHeight(height) {
    height = parseFloat(height);
    //log("setHeight:" + height);
    if(this.rotatedRef == null) {
      this.setReferenceRotation();
    }
    if((this.isWilcomEMB)||(this.isSavedDigitized)) { //check the resize is within 20%
      
      var newHeight = this.fromCanvasDim(height);
      var delta = Math.abs(this.rotatedRef.h - newHeight);
      var twentyPercent = this.rotatedRef.h / 5;
      if(delta > twentyPercent + 1) {
        log("delta (" + delta + ") > twentyPercent (" + twentyPercent + ") changing size...");
        if(newHeight < this.rotatedRef.h) {
          newHeight = this.rotatedRef.h - twentyPercent;
        } else {
          newHeight = this.rotatedRef.h + twentyPercent;
        }
        height = this.toCanvasDim(newHeight);
        this.el.style.height = height + "px";
        
        var width = parseInt(height * this.rotatedRef.a, 10);
        this.el.style.width = width + "px";
        
        return false;
      }
      this.el.style.height = height + "px";
      var width = parseInt(height * this.rotatedRef.a, 10);
      this.el.style.width = width + "px";
      return true;
    } else {
      this.el.style.height = height + "px";
      if((this.maintainAspect)||(this.rotated)) {
        var width = parseInt(height * this.rotatedRef.a, 10);
        this.el.style.width = width + "px";
      }
      return true;
    }
    
  },
  
  setWidth: function ImgItem_setWidth(width) {
    if((this.isWilcomEMB)||(this.isSavedDigitized)) {
      return false;
    } else if((this.maintainAspect)||(this.rotated)) {
      return false;
    }
    this.el.style.width = width + "px";
    return true;
  },
  
  setTop: function ImgItem_setTop(top) {
    this.el.style.top = top + "px";
  },
  setLeft: function ImgItem_setLeft(left) {
    this.el.style.left = left + "px";
  },
  
  resizeFinished:  function(event) {
    if((this.isWilcomEMB)||(this.isSavedDigitized)) {
      this.releaseResizing();
      var dims = d.fromCanvasDims(this.getDims(),this.cViewProcess.productProcess);
      
      //var rDims = this.fromRotatedDims(dims);
      
      this.width = dims.w;
      this.height = dims.h;
      this.top = dims.t;
      this.left = dims.l;
      
      
      this.sizeChanged();
      this.checkPosition();
      //d.itemChanged(true);
      this.setDirty();
      d.selectTab('m','customize'); 
      //d.expandManage();
      
    } else {
      ImageItem.parentClass.method("resizeFinished").call(this);
      if(!this.checkQuality()) {
        d.showQualityWarning();
      }
      this.manualQuality = this.quality; //keep track of the last quality that we manually set...
      if(!this.rotated) { //the aspect ratio could have changed... recalc ref rotation data
        this.setReferenceRotation(0, true);
      }
      this.updateDigitizationNotice(true,true);
    }
  },
  
  //callback fired whenever the position/size has changed..
  checkPosition: function ImgItem_checkPosition() {
    if(this.digitize || this.isWilcomEMB || this.isSavedDigitized) {
      var pos = this.getItemPositioning();
      if(pos != 0) {
        if(this.cropWarning != true) {
          this.addAlert(0,"crop_error", "alert_crop_error", ml("Image outside bounds"), ml("Embroidery images must be completely inside the decoration area. You will need to either move or resize this item before you will be able to save."), true);
          this.cropWarning = true;
        }
        
      } else if(this.cropWarning == true) {
        this.removeAlert(0,"crop_error");
        this.cropWarning = false;
      }
    } else if(d.designerOptions.warnIfOutside()) {
      var pos = this.getItemPositioning();
      if(pos != 0) {
        if(this.cropWarning != true) {
          this.addAlert(1,"crop_warning", "alert_crop_error", ml("Image outside bounds"), ml("You have placed the image partially outside the decoration area and will be cropped."), true);
          this.cropWarning = true;
        }
      } else if(this.cropWarning == true) {
        this.removeAlert(1,"crop_warning");
        this.cropWarning = false;
      }
    }
  },
  
  
  sizeChanged: function ImgItem_sizeChanged() {
    ImageItem.parentClass.method("sizeChanged").call(this);
    this.setQuality();
  },
  
  //called after item is moved to another product
  validate: function ImgItem_validate() {
    this.setQualityWarning(true); //reset back to ok...
    this.checkPosition();
    this.sizeChanged();
  },
  
  setQuality: function ImgItem_setQuality() {
    if(this.isWilcomEMB || this.digitize || this.isSavedDigitized) {
      return;
    }
    
    if(this.qualitySliderContainer == null) {
      return;
    }
    var q = this.getQuality(this.width,this.height,this.cViewProcess.productProcess);
    this.quality = q;
    
    if(q < 0.05) {
      q = 0.05;
    } else if(q > 1) {
      q = 1;
    }
    
    if(q < 0.25) {
      //this.qualitySlider.src = d.pathPrefix + "/images/mp/quality_bad.gif";
	  this.qualitySliderContainer.className="quality_bad";
    } else if(q < 0.75) {
      //this.qualitySlider.src = d.pathPrefix + "/images/mp/quality_med.gif";
	  this.qualitySliderContainer.className="quality_med";
    } else {
      //this.qualitySlider.src = d.pathPrefix + "/images/mp/quality_good.gif";
	  this.qualitySliderContainer.className="quality_good";
    }
    
    //this.qualitySlider.style.width = (60.0 * q) + "px";
	this.qualitySliderContainer.style.width = (60.0 * q) + "px";
    
    this.setQualityWarning(this.checkQuality());
  },
  
  getQuality: function ImgItem_getQuality(width, height, productProcess) {
    if(this.rotatedRef == null) {
      this.setReferenceRotation();
    }
    var dims = this.fromRotatedDims({w:width, h:height});
    var dpi = (parseFloat(this.asset.width) / parseFloat(dims.w)) * productProcess.perfectDPI;
    var dpi2 = (parseFloat(this.asset.height) / parseFloat(dims.h)) * productProcess.perfectDPI;
    //Not sure how this will work with skewing... probably better than below.... 
    //var dpi = (parseFloat(this.asset.width) / parseFloat(width)) * productProcess.perfectDPI;
    //var dpi2 = (parseFloat(this.asset.height) / parseFloat(height)) * productProcess.perfectDPI;
    if(dpi2 < dpi) {
      dpi = dpi2;
    }
    
    var pdpi = productProcess.perfectDPI;
    var mdpi = productProcess.minDPI;
    var ddpi = dpi - mdpi;
    
    var qRange = pdpi - mdpi;
    if(qRange == 0) {
      qRange = 1;
      ddpi += 1;
    }
    
    var q = ddpi / qRange;
    
    log("getQuality: dpi=" + dpi + " minDPI=" + mdpi + " perfectDPI=" + pdpi + " q=" + q + " dims.w=" + dims.w + " dims.h=" + dims.h + " this.width=" + this.width + " this.height=" + this.height + " this.asset.width=" + this.asset.width + " productProcess.perfectDPI=" + productProcess.perfectDPI);
    
    return q;
  },
  
  checkQuality: function ImgItem_checkQuality() {
    if((this.isWilcomEMB)||(this.isSavedDigitized)) {
      return true;
    } else if(this.quality < 0.2) {
      return false;
    }
    return true;
  },
  
  minDims: function ImgItem_minDims(dims) {
    
    var startDPI = this.cViewProcess.productProcess.minDPI + ( (this.cViewProcess.productProcess.perfectDPI - this.cViewProcess.productProcess.minDPI)/3);
    
    
    
    var mScaleRefactor = this.cViewProcess.productProcess.perfectDPI  / startDPI;
    
    //var minScale = this.layoutManager.layoutData.lScale / mScaleRefactor;
    
    log("mScaleRefactor=" + mScaleRefactor);
    
    var mW = this.asset.width * mScaleRefactor;
    var mH = this.asset.height * mScaleRefactor;
    
    
    //log("mW=" + mW + " mH=" + mH + " dims.w=" + dims.w + " dims.h=" + dims.h);
    //var mW = this.asset.width * 72 / parseFloat(startDPI);
    //var mH = this.asset.height * 72 / parseFloat(startDPI);
    
    if(mW < dims.w) {
      dims.w = mW;
    }
    if(mH < dims.h) {
      dims.h = mH;
    }
    
    log(dims);
    return dims;
  },
  
  //check if we can rescale this item using desiredScale to work with process...
  //desiredScale is the rescale in design canvas sizes...
  checkScale: function ImgItem_checkScale(desiredScale, process) {
    
    
    //we have the rescale factor when in design canvas....
    
    //convert to design scale -> desiredScale -> process.unscale_from_design_scale
    
    var scale = this.cViewProcess.productProcess.designScale / desiredScale / process.designScale;
    
    var testHeight = parseFloat(this.height) * scale;
    var testWidth = parseFloat(this.width) * scale;
    var scaleFailed = false;
    if(!this.cViewProcess.productProcess.process.usesDPI) {
      //we cannot rescale this image more then 20%....
      var vDiff = parseFloat(testHeight - this.asset.height) / parseFloat(this.asset.height);
      var hDiff = parseFloat(testWidth - this.asset.width) / parseFloat(this.asset.width);
      
      if(Math.abs(vDiff) > 0.2 || Math.abs(hDiff) > 0.2 ) {
        log("rescale is over 20%: desiredScale=" + desiredScale + ", scale=" + scale + ", testHeight=" + testHeight + " asset.height=" + this.asset.height + ", testWidth=" + testWidth + " asset.height=" + this.asset.height);
        var reScale = 0;
        //we are scaling over 20%... lets cap it at 20%....
        if(Math.abs(vDiff) > Math.abs(hDiff)) {
          //vertically scaled more...
          if(vDiff > 0) {
            reScale = testHeight / (this.asset.height * 1.2);
          } else {
            reScale = testHeight / (this.asset.height * 0.8);
          }
        } else {
          if(hDiff > 0) {
            reScale = testWidth / (this.asset.width * 1.2);
          } else {
            reScale = testWidth / (this.asset.width * 0.8);
          }
        }
        testHeight /= reScale;
        testWidth /= reScale;
        scaleFailed = true;
        log("fixed scale: testHeight=" + testHeight + " testWidth=" +testWidth);
      }
    } else {
      
      // if(testHeight > this.height) { //only care if we scaled up....
        var quality = this.getQuality(testWidth,testHeight,process);
        log("Checking scale, scale=" +scale + " testHeight=" +testHeight + " testWidth=" + testWidth + " quality=" + quality + " this.asset.width=" + this.asset.width + " this.asset.height=" + this.asset.height );
        if((quality < 0.33) && (this.manualQuality == null || this.manualQuality > quality)) { //below 33% quality and below last manually set quality (if manually set)...
          var targetDPI = process.minDPI + (process.perfectDPI - process.minDPI) / 3; // 1/3 between min and perfect dpi
          
          var reScale = 0;
          var dpi = (parseFloat(this.asset.width) / parseFloat(testWidth)) * process.perfectDPI;
          var dpi2 = (parseFloat(this.asset.height) / parseFloat(testHeight)) * process.perfectDPI;
          if(dpi2 < dpi) {
            //height is the bigger problem...
            var betterHeight = parseFloat(this.asset.height) / (targetDPI / process.perfectDPI);
            reScale = testHeight / betterHeight;
            log("Check Scale Failed: targetDPI=" + targetDPI + " height_dpi=" + dpi2 + " width_dpi=" + dpi + " betterHeight=" + betterHeight + " reScale=" + reScale);
          } else {
            var betterWidth = parseFloat(this.asset.width) / (targetDPI / process.perfectDPI);
            reScale = testWidth / betterWidth;
            log("Check Scale Failed: targetDPI=" + targetDPI + " height_dpi=" + dpi2 + " width_dpi=" + dpi + " betterWidth=" + betterWidth + " reScale=" + reScale);
          }
          testHeight /= reScale;
          testWidth /= reScale;
          scaleFailed = true;
          log("Check Scale Failed: testHeight=" + testHeight + " testWidth=" + testWidth);
          
        } else {
          log("Scale check passed this.manualQuality=" + this.manualQuality);
        }
      // } else {
      //   log("Skipping scale check because rescaled smaller");
      // }
    }
    
    if(scaleFailed) { //we could rescale amount wanted.. we have recalced the final w/h.. lets get the scale back from that...
      scale = testHeight / parseFloat(this.height);
      log("scale1=" + scale);
      var scale2 = scale * process.designScale;
      log("scale2=" + scale2);
      
      desiredScale = this.cViewProcess.productProcess.designScale / scale2;
      log("scale3=" + desiredScale);
      
      scale2 = this.cViewProcess.productProcess.designScale / desiredScale / process.designScale;
      
      testHeight = parseFloat(this.height) * scale2;
      testWidth = parseFloat(this.width) * scale2;
      log("scale=" + scale + " scale2=" + scale2 + " testHeight=" + testHeight + " testWidth=" + testWidth + " check q=" + this.getQuality(testWidth,testHeight,process));
      
    }
    return desiredScale; //default behaviour
  },
  
  serializeToOptions: function Item_serializeToOptions(o) {
    o = ImageItem.parentClass.method("serializeToOptions").call(this,o);
    var colors = "";
    if(this.colors != null) {
      for(var i=0;i<this.colors.length;i++) {
        colors += this.colors[i] + ":";
      }
    }
    o.c = colors;
    
    if(this.rotateWidget!=null) {
      o.rot = this.rotateWidget.value;
    } else if(this.options.rot) { 
      o.rot = this.options.rot;
    }

    if(this.maintainAspect) {
      o.ar = "1";
    } else {
      o.ar = "0";
    }
    if(this.itemType==0) {
      var realSize = this.getRealDims();
      o.rw = realSize.w;
      o.rh = realSize.h;
      
      o.b=this.borderId;
      o.tc = this.transparentColor;
      
      if((this.digitize)&&(!this.splitColors)) {
        o.spc=0;
        o.po = this.percentOpaque;
      } else if(this.splitColors) {
        o.spc = 1;
      }
      if((this.digitize)&&(this.digitizedAsset.primaryItem() == this)) {
        o.pri_dig=1;
      }
      
      if(this.colorCount != null) {
        o.cc = this.colorCount;  
      }
      
      if (this.colorWay != null) {
        o.cw = this.colorWay ;
      }
      
      //effects
      var eo = {};
      hasEffects = false;
      for(k in this.effects) {
        var e = this.effects[k];
        if(e != null) {
          var hasOpt = false;
          eoo = {};
          for(ck in e) {
            eoo[ck] = e[ck];
            hasOpt = true;
          }
          if(hasOpt) {
            hasEffects = true;
            eo[k] = eoo;
          }
        }
      }
      if(hasEffects) {
        o.eff = eo;
      }
    }
    return o;
  },
  
  
  serializeOLD: function ImgItem_serialize(queryComponents, prefix) {
    if(prefix==null) {
      prefix = "t[" + this.id + "]";
    }
    if(queryComponents==null) {
      queryComponents = new Array();
    }
    
    ImageItem.parentClass.method("serialize").call(this,queryComponents,prefix);
    //this.parentCall("serialize",queryComponents);
    
    var colors = "";
    if(this.colors != null) {
      for(var i=0;i<this.colors.length;i++) {
        colors += this.colors[i] + ":";
      }
    }
    queryComponents.push(encodeURIComponent(prefix + "[c]") + "=" + encodeURIComponent(colors));
    
    if(this.rotateWidget!=null) {
      queryComponents.push(encodeURIComponent(prefix + "[rot]") + "=" + encodeURIComponent(this.rotateWidget.value));
    } else if(this.options.rot) { 
      queryComponents.push(encodeURIComponent(prefix + "[rot]") + "=" + encodeURIComponent(this.options.rot));
    }

    if(this.maintainAspect) {
      queryComponents.push(encodeURIComponent(prefix + "[ar]") + "=" + encodeURIComponent("1"));
    } else {
      queryComponents.push(encodeURIComponent(prefix + "[ar]") + "=" + encodeURIComponent("0"));
    }
    if(this.itemType==0) {
      var realSize = this.getRealDims();
      queryComponents.push(encodeURIComponent(prefix + "[rw]") + "=" + encodeURIComponent(realSize.w));
      queryComponents.push(encodeURIComponent(prefix + "[rh]") + "=" + encodeURIComponent(realSize.h));
      
      queryComponents.push(encodeURIComponent(prefix + "[b]") + "=" + this.borderId);
      queryComponents.push(encodeURIComponent(prefix + "[tc]") + "=" + encodeURIComponent(this.transparentColor));
      
      if((this.digitize)&&(!this.splitColors)) {
        queryComponents.push(encodeURIComponent(prefix + "[spc]") + "=0");
        queryComponents.push(encodeURIComponent(prefix + "[po]") + "=" + encodeURIComponent(this.percentOpaque));
      } else if(this.splitColors) {
        queryComponents.push(encodeURIComponent(prefix + "[spc]") + "=1");
      }
      if((this.digitize)&&(this.digitizedAsset.primaryItem() == this)) {
        queryComponents.push(encodeURIComponent(prefix + "[pri_dig]") + "=1");
      }
      
      if(this.colorCount != null) {
        queryComponents.push(encodeURIComponent(prefix + "[cc]") + "=" + encodeURIComponent(this.colorCount));  
      }
      
      if (this.colorWay != null) {
        queryComponents.push(encodeURIComponent(prefix + "[cw]") + "=" + encodeURIComponent(this.colorWay)) ;
      }
      this.serialiseState(prefix + "[eff]", this.effects, queryComponents);
    }
  },
  
  getRotation: function ImgItem_getRotation() {
    if(this.rotateWidget!=null) {
      return this.rotateWidget.value;
    } else if(this.options.rot) { 
      return this.options.rot;
    }
    return 0;
  },
  
  setAsset: function ImgItem_setAsset(asset) {
    this.asset = asset;
    this.setName(asset.name);
    if(this.el != null) {
      this.updateImageSrc();
      /*
      if(this.getRotation() != 0) {
        this.setSrc(d.pathPrefix + "/designer/rotate_image?id=" + this.asset.id + "&deg=" + this.getRotation() + "&ts=" + new Date().getTime());
      } else {
        this.setSrc(this.asset.getUrl());
        var self = this;
        this.asset.loadWorkingAsset(function() { self.setSrc(self.asset.getWUrl()); log("loaded set asset");});
      }
      */
    }
    if(this.thumb!=null) {
      var sizes = this.asset.scale(100,100);
      this.thumb.src = this.asset.getWUrl();
      this.thumb.width = parseInt(sizes.w, 10);
      this.thumb.height = parseInt(sizes.h, 10);
    }
    
    if(this.titleThumb!=null) {
      var sizes = this.asset.scale(15,20);
      this.titleThumb.src = this.asset.getWUrl();
      this.titleThumb.width = parseInt(sizes.w, 10);
      this.titleThumb.height = parseInt(sizes.h, 10);
    }
    if(this.el != null) {
      this.initColors();
      this.setQuality();
      this.setPosition();
    }
  },
  
  selectTab: function ImgItem_selectTab(tab, id) {
    if(this.oldTabName != null) {
      if(this.oldTabName==tab) {
        return;
      }
      
      if(this.oldTabName == "effects") {
        if(this.effectsToBeApplied) {
          if(confirm(ml("Do you want to apply the selected effects?"))) {
            this.effectChanged(true);
          } else {
            return;
          }
        }
      }
      var oldTab = $('i_' + this.oldTabName + "_tab_" + id);
      oldTab.style.display='none';
      oldTab = $('i_' + this.oldTabName + "_" + id);
      oldTab.className = "et_unselected_tab";
    }
    var newTab = $('i_' + tab + "_tab_" + id);
    newTab.style.display='';
    newTab = $('i_' + tab + "_" + id);
    newTab.className = "et_selected_tab";
    this.oldTabName = tab;
    if(!this.borderInit) {
      //var html = '<table cellpadding="0" cellspacing="0">';
	  var html = '<ul>';
      for(var i=0; i < borderEffects.size(); i++) {
		/*if(i%5 == 0) {
			if(i==0) {
				html += "<tr>";
			} else {
				html += "</tr><tr>";
			}
		}*/
		
        var border = borderEffects[i];
        var url = "";
        if(border[0] == 0) {
          url = d.pathPrefix + "/images/noborder.gif";
        } else {
          url = d.pathPrefix + "/border/image/" + border[0] + "/thumb-ppr.gif";
        }
        var clazz = "et_effect";
        if(this.borderId == border[0]) {
          clazz = "et_effect select";
        }
        html += '<li class="' + clazz + '" id="i_b_' + this.elId + '_' + border[0] + '" onmouseover="ieOMO(this);" onmouseout="ieOMOu(this);"  onclick="ibOMc(' + this.id + ',' + i + ');"><img src="' + url + '"/></li>';
      }
      //html += "</tr></table>";
	  html += "</ul>";
      var div = $("i_borders_list_" + this.elId);
      div.innerHTML = html;
      this.borderInit = true;
      d.borderIconsLoaded = true;
    
    }
  },
  
  getWorkingState: function ImgItem_getWorkingState() {
    if(this.workingState == null) {
      this.workingState = {};
      for(k in this.effects) {
        var e = this.effects[k];
        var t = {};
        for(ek in e) {
          t[ek] = e[ek];
        }
        this.workingState[k] = t;
      }
    }
    return this.workingState;
  },
  
  effectClick: function ImgItem_effectClick(eIdx) {
    var effect = imageEffects[eIdx];
    var eCode = effect[0];
    var workingState = this.getWorkingState();
    var hasChanged = false;
    if(workingState[eCode] == null) {
      workingState[eCode] = {};
      hasChanged = true;
    }
    this.loadEffectPanel(workingState[eCode], effect);
    if(hasChanged) {
      this.effectChanged();
      this.updateEffectSelection(this.getWorkingState());
    }
  },
  
  loadEffectPanel: function ImgItem_loadEffectPanel(state, effect) {
    if((effect!= null)&&(this.currentEffect == effect)) {
      return;
    }
    var html = "<div class='effect_controls'>";
	html+='<div class="effect_header">';
	
    if(effect!=null) {
      html += '<h4>' + effect[1] + '</h4><a href="#" id="e_rem_' + this.elId + '">Remove</a>';
	  html+='</div>';
    } else {
      html += '<h4>No Effects Applied</h4>';
	  html+='</div>';
	  //html+='<p>Click on an effect to apply it to your image.</p>';
    }
    this.settingEffectsPanel = true;
    
    
    var self = this;
    var callback = function() { self.effectChanged(); };
    
    this.currentControls = {};
    this.currentEffect = effect;
	var lineHtml="";
    if(effect!=null) {
      for(var i=4; i < effect.length;i++) {
        var controlDef = effect[i];
        if(controlDef[2]!="P") {
          var clz = controlClasses[controlDef[2]];
          log(controlDef[2]);
          var control = new clz(controlDef[0], controlDef[1], effect, controlDef[3],callback, this.elId);
          this.currentControls[control.code] = control;
          
          lineHtml += '<li>' + control.buildHTML() + '</li>';
        } else {
          state[controlDef[1]] = "1";
        }
      }
    }
    
    html += ''+
	'<div class="et_list et_effect_control">'+
		'<div class="et_preview">'+
			'<div class="title"><input type="checkbox" id="e_p_c_' + this.elId + '"/><label>Preview</label></div>'+
			'<img id="e_p_i_' + this.elId + '" style="display:none;"/>'+
		'</div>'+
		'<div class="et_right">'+
			'<ul>'+lineHtml+'</ul>'+
			'<div class="et_submit">'+
			'<a href="#" id="e_p_a_' + this.elId + '" class="okay">apply</a>'+
			'<a href="#" id="e_p_ac_' + this.elId + '" class="cancel">cancel</a>'+
			'</div>'+
			
			//'<img src="' + d.pathPrefix + '/images/mp/tick.gif" alt="Apply" title="Apply" style="display:none;cursor:pointer;" id="e_p_a_' + this.elId + '"/>'+
			//'<img src="' + d.pathPrefix + '/images/mp/cross.gif" alt="Cancel" title="Cancel" style="display:none;cursor:pointer;" id="e_p_ac_' + this.elId + '"/>'+
		'</div>'+
	'</div>'+
	'</div>';
    
    var panel = $("i_aeffects_list_" + this.elId);
    panel.innerHTML = html;
    
    for(k in this.currentControls) {
      var control = this.currentControls[k];
      control.bindControls();
      control.loadFromState(state, true);
    }
    
    this.settingEffectsPanel = false;
    
    if(this.showEffectPreview == null) {
      this.showEffectPreview = d.showEffectPreview;
    }
    var cb = $("e_p_c_" + this.elId);
    if(this.showEffectPreview) {
      cb.checked = true;
    }
    cb.onclick = function() {
      d.showEffectPreview = cb.checked;
      self.showEffectPreview = cb.checked;
      self.effectChanged();
    };
    
    var button = $("e_p_a_" + this.elId);
    if(this.effectsToBeApplied) {
      button.style.display='';
    }
    button.onclick = function() {
      self.effectChanged(true);
	  return false;
    };
    
    var button = $("e_p_ac_" + this.elId);
    if(this.effectsToBeApplied) {
      button.style.display='';
    }
    button.onclick = function() {
      //self.effectChanged(true);
      self.workingState = null;
      self.effectsToBeApplied = false;
      self.selectDefaultEffect(self.effects);
	  return false;
    };
    
    
    if(effect != null) {
      var rem = $("e_rem_" + this.elId);
      rem.onclick = function() {
        self.removeEffect(effect);
        return false;
      };
      if(effect[3].single) {
        if((this.currentSingleEffect != null)&&(this.currentSingleEffect !=effect))  {
          this.removeEffect(this.currentSingleEffect, true);
        }
        this.currentSingleEffect = effect;
      }
    }
    
  },
  
  removeEffect: function ImgItem_removeEffect(effect, noBubble) {
    this.currentEffect = null;
    var eCode = effect[0];
    log("removeEffect:" + eCode);
    state = this.getWorkingState();
    state[eCode] = null;
    if(noBubble!=true) {
      this.effectChanged();
      this.selectDefaultEffect(state);
      this.effectChanged();
    }
  },
  
  selectDefaultEffect: function ImgItem_selectDefaultEffect(state) {
    this.updateEffectSelection(state);
    var effectLeft = false;
    for(var i = 0; i < imageEffects.size(); i++) {
      var effect = imageEffects[i];
      var td = $('i_ef_' + this.elId + '_' + effect[0]);
      var eCode = effect[0];
      if(state[eCode] != null) {
        this.loadEffectPanel(state[eCode], effect);
        effectLeft = true;
        break;
      }
    }
    if(!effectLeft) {
      this.loadEffectPanel(null, null);
    }
  },
  
  updateEffectSelection: function ImgItem_updateEffectSelection(state) {
    for(var i = 0; i < imageEffects.size(); i++) {
      var effect = imageEffects[i];
      var td = $('i_ef_' + this.elId + '_' + effect[0]);
      if(state[effect[0]] != null) {
        log(effect[0] + " is on");
        td.className = "et_effect select";
      } else {
        td.className = "et_effect";
      }
    }
  },
  
  effectChanged: function ImgItem_effectChanged(skipPreview) {
    if(this.settingEffectsPanel){
      return;
    }
    this.updateWorkingState();
    if( (skipPreview == true) || (!this.showEffectPreview)) {
      this.effects = this.workingState;
      this.workingState = null;
      log("effectChanged: update image");
      this.effectsToBeApplied = false;
       $("e_p_a_" + this.elId).style.display="none";
       $("e_p_ac_" + this.elId).style.display="none";
       this.updateImageSrc();
       this.setDirty();
       //d.itemChanged(true);
    } else {
      this.effectsToBeApplied = true;
      $("e_p_a_" + this.elId).style.display="";
      $("e_p_ac_" + this.elId).style.display="";
      var bgColorObj = d.currentCProduct.getSelectedColor();
      var bgColor = "#FFFFFF";
      if(bgColorObj != null) {
        bgColor = bgColorObj.colors[0][0];
      }
      
      url = d.pathPrefix + "/designer/get_image?id=" + this.asset.id + this.getColorParam() + "&preview=1&bg_color=" + encodeURIComponent(bgColor) + "&" + this.serialiseState("es", this.getWorkingState()).join('&');
      
      var previewImg = $("e_p_i_" + this.elId);
      previewImg.style.display="";
      setImageUrl(previewImg, previewImg, url);
      log("effectChanged: update preview");
    }
    
  },
  
  updateWorkingState: function ImgItem_updateWorkingState() {
    if(this.currentEffect == null) {
      return;
    }
    var eCode = this.currentEffect[0];
    var state = this.getWorkingState();
    var effectState = state[eCode];
    if(effectState == null) {
      effectState = {};
      state[eCode] = effectState;
    }
    for(k in this.currentControls) {
      var control = this.currentControls[k];
      control.saveToState(effectState);
    }
  },
  
  serialiseState: function ImgItem_serialiseState(prefix, state, queryComponents) {
    log(state);
    if(prefix==null) {
      prefix = "t[" + this.id + "][eff]";
    }
    if(queryComponents==null) {
      queryComponents = new Array();
    }

    for(k in state) {
      var e = state[k];
      if(e != null) {
        log(e);
        for(ck in e) {
          //log("serialiseStateA:" + ck);
          queryComponents.push(encodeURIComponent(prefix + "[" + k + "][" + ck + "]") + "=" + encodeURIComponent(e[ck]));
        }
      }
      
    }
    
    return queryComponents;
  },
  
  hasEffects: function ImgItem_hasEffects() {
    for(k in this.effects) {
      return true;
    }
    return false;
  },
  
  borderClick: function ImgItem_borderClick(bIdx) {
    var border = borderEffects[bIdx];
    if(this.borderId == border[0]) {
      return;
    }
    $("i_b_" + this.elId + '_' + this.borderId).className = "et_effect";
    this.borderId = border[0];
    $("i_b_" + this.elId + '_' + this.borderId).className = "et_effect select";
    this.updateImageSrc();
  },
  
  //find the percent of an image thats opaque...
  calculatePercentOpaque: function ImgItem_calculatePercentOpaque() {
    if(!this.splitColors) {
      return this.percentOpaque;
    } else {
      var totalPercent = parseFloat(this.asset.getMetaData(["split_colors", this.colorCount, "percent_transparent"], 0));
      var counts = this.asset.getMetaData(["split_colors", this.colorCount, "counts"], null);
      for(var i=0; i < this.colorCount; i++) {
        if((this.colors[i] != null) && (this.colors[i] == "Transparent")) {
          var colorPercent = counts[i];
          totalPercent += colorPercent;
        }
      }
      log("Percent Transparent = " + totalPercent);
      return 1.0 - totalPercent;
    }
  },
  
  //get area in sq inches of the image
  calculateArea: function ImgItem_calculateArea() {
    //get the real width/height of image
    var realSize = this.getRealDims();
    //convert to inches
    var dpi = parseFloat(this.cViewProcess.productProcess.perfectDPI);
    this.widthInches = parseFloat(realSize.w) / dpi;
    this.heightInches = parseFloat(realSize.h) / dpi;
    //make area
    log("dpi=" + dpi + ", widthInches=" + this.widthInches + ", heightInches=" + this.heightInches);
    var area = this.widthInches * this.heightInches;
    return area;
  },
  
  updateDigitizationCosts: function ImgItem_updateDigitizationCosts() {
    var percentOpaque = this.calculatePercentOpaque();
    var area = this.calculateArea();
    this.digitizationArea = area * percentOpaque;
    var process = this.cViewProcess.productProcess.process;
    
    this.digitizationFee = process.digitizationFeePerInch ? process.digitizationFee * this.digitizationArea : process.digitizationFee;
    this.digitizationFee *= this.cView.configuredProduct.getPercentMarkup(true);
    
    if(this.digitizedAsset.primaryItem() == this) {
      log("Primary Digitization Found");
    } else {
      log("Secondary Digitization Found");
    }
    this.stitchCount = this.digitizationArea * process.stitchesPerInch;
    log("updateDigitizationCosts: digitizationArea=" + this.digitizationArea +",  digitizationFee=" + this.digitizationFee + ", stitchCount=" + this.stitchCount, true);
  },
  
  updateDigitizationNotice: function ImgItem_updateDigitizationNotice(updateCosts, updatePrice) {
    if(this.digitize) {
      if(updateCosts)  this.updateDigitizationCosts();
      var notice = null;
      if(this.digitizedAsset.primaryItem() == this) {
        if(!this.splitColors) {
          notice = ml('Digitization Fee = %1s<br />Size =%2ssq inches<br/>You are looking at the original version of the image you have uploaded. The image will be professionally digitized to at most %3s colors.',
          [d.formatPrice(d.roundPrice(this.digitizationFee), "fee_currency_code"), this.digitizationArea.toFixed(2), this.cViewProcess.productProcess.process.maxColors]);
        } else {
          notice = ml('Digitization Fee = %1s<br />Size =%2ssq inches<br/>Colors = Approximated. Final thread colors may vary.',
          [d.formatPrice(d.roundPrice(this.digitizationFee), "fee_currency_code"), this.digitizationArea.toFixed(2)]);
        }
      } else {
        if(!this.splitColors) {
          notice = ml('The price to digitize this image is included against another item in your cart.<br />Size =%1ssq inches<br/>You are looking at the original version of the image you have uploaded. The image will be professionally digitized to at most %3s colors.',
          [this.digitizationArea.toFixed(2), this.cViewProcess.productProcess.process.maxColors]);
        } else {
          notice = ml('The price to digitize this image is included against another item in your cart.<br />Size =%1ssq inches<br/>Colors = Approximated. Final thread colors may vary.',
          [this.digitizationArea.toFixed(2)]);
        }
      }
      if(this.digNotice != true) {
        this.addAlert(2,"digitization_notice", "alert_digitization_notice", ml("Digitization Required"), notice, false);
        this.digNotice = true;
      } else {
        this.updateAlertMessage(2, "digitization_notice", ml("Digitization Required"), notice) ;
      }
      
      if(updatePrice) {
        d.currentProductType.updatePrice();
      }
    }
  },
  
  //check if this is the primary/secondary asset... restrict accordingly
  refreshDigitizedAsset: function ImgItem_refreshDigitizedAsset(event) {
    log("refreshDigitizedAsset: this.digitizedAsset.items.list.length=" + this.digitizedAsset.items.list.length);
    if(this.digitizedAsset.items.list.length > 1) { //start locking down...
      this.allowResize = false;
      var primaryItem = this.digitizedAsset.primaryItem();
      var isPrimary = (this == primaryItem); 
      if(this.hasDigLockNotice) {
        if((event & DIG_EVENT_PRIMARY) == DIG_EVENT_PRIMARY) { //the warning message may have changed...remove it so it can be redone....
          this.removeAlert(1,"dig_lock");
          this.hasDigLockNotice = false;
        }
      }
      if((event & DIG_EVENT_PRIMARY) == DIG_EVENT_PRIMARY) { 
        this.initColors();
      } else if((event & DIG_EVENT_COLOR) == DIG_EVENT_COLOR) {
        if(!isPrimary) { //the colro changed on the primary.. reflect here...
          this.colors = primaryItem.colors;
          this.colorCount = primaryItem.colorCount
          this.transparentColor = primaryItem.transparentColor;
          this.updateDigitizationNotice(true, true);
        }
        this.initColors();
        this.updateImageSrc();
      }
      
      if(!this.hasDigLockNotice) {
        if(isPrimary) {
          this.addAlert(1, "dig_lock", "alert_digitization_lock", ml("Digitization Lock"), ml("This image is now locked because it has been added multiple times for digitization."), false);
        } else {
          this.addAlert(1, "dig_lock", "alert_digitization_lock", ml("Digitization Lock"), ml("This image is now locked because it has been added multiple times for digitization. To change colors go to the first instance of this image."), false);
        }
        this.hasDigLockNotice = true;
      }
      if(this.aspectEl != null) this.aspectEl.disabled = true;
      this.setFeature("size_arrows", false);
    } else {
      this.allowResize = true;
      if(this.hasDigLockNotice) { //we are moving from lock to unlocked....
        this.removeAlert(1,"dig_lock");
        this.hasDigLockNotice = false;
        this.initColors();
      } else {
        if((event & DIG_EVENT_COLOR) == DIG_EVENT_COLOR) {
          this.initColors();
        }
      }
      if(this.aspectEl != null) this.aspectEl.disabled = this.rotated;
      this.setFeature("size_arrows", true);
    }
  },
  
  isSecondaryDigitization: function() {
    if(this.digitize) {
      //its a digitized asset....
      var primary = this.digitizedAsset.primaryItem();
      if(primary != this) {
        return true;
      }
    }
    return false;
  },
  
  lockedDigitization: function() {
    if(this.digitize) {
      if(this.digitizedAsset.items.list.length > 1) {
        return true;
      }
    }
    return false;
  }
  
});
