var Designer = Class.create({
  CLASSDEF: {
      name: 'Designer'
  },
  
  initialize: function D_initialize(pathPrefix, designMode, inPopup, curGlyph, curCode, priceRounding, price99, useAnalytics, cMod, tMod, declibMarkup, lengthUnit, priceFormat) {
    this.selected_tabs = {"d":"layout","m":"customize","p":"mens", "i":"user"};
    this.cart = new Cart();
    this.decorationLibraryManager = new DecorationLibraryManager(this);
    this.teamNameTemplates = new TeamNameTemplates();
    this.chargeDecorationLibraries = {};
    this.assets = {};
    this.designerOptions = new DesignerOptions(DFLAG_DEFAULTS);
    
    this.debugAjax = 0;
    
    this.currentCProduct = null;
    this.productTypes = new Hash();
    this.currentProductType = null;
    this.nextId = 1;
    this.nextItemId = 1;
    this.pathPrefix = pathPrefix;
    this.sizer = null;
    this.productsById = new Hash();
    this.inPopup = inPopup;
    this.extraExternalParams = "";
    this.hideQualityWarning = false;
    this.useAnalytics = useAnalytics;
    this.showGrid = true;
    this.autoCheckout = true;
    this.extraCallbackParams = "";
    
    this.defaultMarkupType = 0;
    this.defaultMarkupAmount = 20;
    
    this.discounts = [];
    this.affiliateDiscounting = true;
    this.declibMarkup = declibMarkup;
    
    this.lengthUnit = lengthUnit;
    
    
    this.priceRounding = priceRounding;
    this.price99 = price99;
    this.priceFormat = priceFormat;
    
    this.imagePopupLoaded = false;
    
    this.defaultQtyDisabled = false;
    if(designMode=="shop") {
      this.mode = DESIGNER_MODE_SHOP;
    } else if(designMode=="configure") {
      this.mode = DESIGNER_MODE_CONFIGURE;
     } else if(designMode=="configure_new") {
      this.mode = DESIGNER_MODE_CONFIGURE;
      this.configuringNewProduct = true;
    } else if(designMode=="amend") {
      this.mode = DESIGNER_MODE_AMEND; 
      this.defaultQtyDisabled = true;
      
    } else {
      this.mode = DESIGNER_MODE_VIEW_CUSTOM_PRODUCT;
    }
    
    this.currentCanvasType = 0; //LAYOUT
    this.zoom = 1; //400x400 (LAYOUT)
    
    var re = new RegExp("\\[PATH_PREFIX\\]", "g");
  
    types[0] = types[0].replace(re,pathPrefix);
    types[1] = types[1].replace(re,pathPrefix);
    
    type_min = type_min.replace(re,pathPrefix);
    
    this.layoutViewUrlCID = new RegExp("\\[CID\\]", "g");
    this.layoutViewUrlS = new RegExp("\\[S\\]", "g");
    this.layoutViewUrlSc = new RegExp("\\[SC\\]", "g");
    
    this.allowedItemTypes = null;
    
    
    Ajax.Responders.register({
      onException: function D_onException(aj, ex) {
        try {
          log("Exception Occured\nError name: " + ex.name + "\nError message: " + ex.message, true);
          alert("Exception Occured\nError name: " + ex.name + "\nError message: " + ex.message);
          log(ex); //this was commented out.. why?
        } catch(e) {}
        throw ex;
      }
    });
    
    
    
    
    this.onKeyUpEvent = this.onKeyUp.bindAsEventListener(this);
    Event.observe(document, "keyup", this.onKeyUpEvent);
    
    Event.observe(document.body, "mousedown", backgroundClicked);
    
    this.onQtyDDBgEvent = this.onQtyDDBg.bindAsEventListener(this);
    
    this.onCopyBgEvent = this.onCopyBg.bindAsEventListener(this);
    
    this.showEffectPreview = true;
    
    this.effectIconsLoaded = false;
    this.borderIconsLoaded = false;
    this.preloadEffectIndex = -1;
    this.preloadBorderIndex = -1;
    
    //currency information
    this.curGlyph = (curGlyph==null) ? "$" : curGlyph; 
    this.curCode = (curCode==null) ? "USD" : curCode;
    //currency modifier
    if(cMod==null) {
      this.cMod = 1;
    } else {
      this.cMod = cMod;
    }
    //tax modifier
    if(tMod==null) {
      this.tMod = 1;
    } else {
      this.tMod = tMod;
    }
    
    
    if(pwCurCur!=null) {
      this.curGlyph = pwCurCur[2];
      this.curCode = pwCurCur[1];
      this.cMod = pwCurModifier;
      var self = this;
      pwCurRegisterArea(0, null, null, null, null, null, function(pwCurCur, pwCurBCur, pwCurModifier) {
          self.curGlyph = pwCurCur[2];
          self.curCode = pwCurCur[1];
          self.cMod = pwCurModifier;
          //redisplay prices here..
          self.cart.updateCartPrice(true);
          self.currentCProduct.updateCartPrice(false);
          self.currentProductType.updatePrice();
          d.cart.products.each(function(product){
            for (var viewId in product.views) {
              for (var areaId in product.views[viewId].areas) {
                for (var itemId in product.views[viewId].areas[areaId].allItems) {
                  var item = product.views[viewId].areas[areaId].allItems[itemId];
                  if(item.updateDigitizationNotice) item.updateDigitizationNotice(true, true);
                }
              }
            }
          });
      });
    } else {
      log("pwCurCur is null");
    }
    
    
    this.defaultProcess = null;
    
    this.priceTables = {};
    if(priceTableData != null) {
      for(var i=0; i < priceTableData.length; i++) {
        var pt = new PriceTable(priceTableData[i]);
        this.priceTables[pt.id] = pt;
      }
    }
    
    this.customProducts = {};
    
    this.contentTopEl = $("top_of_content");
    this.translateParams = null;
  },
  
  setDesignerOptions: function D_setDesignerOptions(flags) {
    this.designerOptions = new DesignerOptions(flags);
  },
  
  setDesignElements: function D_setDesignElements(sizer, designPane) {
    this.sizer = sizer;
    this.designPane = designPane;
    
    this.roSizers = new Hash();
    
    this.roSizers["TR"] = $("ts_tr");
    this.roSizers["TL"] = $("ts_tl");
    this.roSizers["BR"] = $("ts_br");
    this.roSizers["BL"] = $("ts_bl");
    
  },
  
  setManagePaneContainer: function D_setManagePaneContainer(el) {
    this.managePaneContainer = el;
  },
  
  setDefaultProcess: function D_setDefaultProcess(processId) {
    this.userSelectedProcessId = processId; 
    this.defaultProcess = processes.byId[processId];
  },
  
  setDebugAjax: function D_setDebugAjax(doDebug) {
    this.debugAjax = doDebug;
  },
  
  ajaxUrl: function D_ajaxUrl(url) {
    if(this.translateParams != null) {
      url = addUrlParam(url, "translate=" + this.translateParams);
    }
    if(this.debugAjax != 0) {
      return addUrlParam(url, "email_request_log=" + this.debugAjax);
    } else {
      return url;  
    }
  },
  
  addChargeDecorationLibrary: function D_addChargeDecorationLibrary(id, range1price, range2price, range3price, range4price, range5price, range6price, range7price) {
    var declib = new ChargeDecorationLibrary(range1price, range2price, range3price, range4price, range5price, range6price, range7price);
    this.chargeDecorationLibraries[id] = declib;
    return declib;
  },
  
  addProductType: function D_addProductType(id, options) {
    var pt = new ProductType(id, options);
    this.productTypes[pt.id] = pt;
    return pt;
  },
  
  addProduct: function D_addProduct(product) {
    log("Adding product " + product.id + " to cache");
    this.productsById[product.id] = product;
  },
  
  addCustomProduct: function D_addCustomProduct(id, options) {
    var cp = new CustomProduct(id, options);
    this.customProducts[cp.id] = cp;
  },
  
  getProduct: function D_getProduct(productId, callback, asyncContainer) {
    if(this.productsById[productId]!=null) {
      if(callback!=null) {
        callback(this.productsById[productId]);
      }
      return this.productsById[productId];
    }
    if(callback!=null) {
      var self = this;
      this.getData({pid:productId}, function(transport) {
        log("getProduct callback");
        if(self.productsById[productId]!=null) {
          if(callback!=null) {
            callback(self.productsById[productId]);
          }
        } else {
          log(self);
          alert("Unable to load product " + productId);
        }
      }, asyncContainer);
    }
    return null;
  },
  
  getData: function D_getData(params, callback, asyncContainer) {
    var p = "m=" + this.mode + "&";
    for(k in params) {
      p += k + "=" + params[k] + "&";
    }
    var asyncKey = null;
    if(asyncContainer) {
      asyncKey = asyncStart(asyncContainer);
    }
    var t2 = new Ajax.Request(d.ajaxUrl(d.pathPrefix + "/js/getdata.js?" + p), {asynchronous:true, evalScripts:true, onComplete: function D_onComplete(response) {
        if(asyncKey!=null) {
          asyncFinish(asyncKey);
        }
        callback(response);
      }
     });
  },
  
  addAsset: function D_addAsset(options) {
    var asset = new Asset(options, this);
    this.assets[asset.id] = asset;
    return asset;
  },
  
  addPriceToUpdate: function D_addPriceToUpdate(el_id, pp_id) {
    if(!d.pricesToUpdate) d.pricesToUpdate = [] ;
    d.pricesToUpdate.push({id: pp_id, ele: el_id+pp_id}) ;
  },
  
  selectCurrentProductType: function D_selectCurrentProductType(id, doUpdate) {
    this.currentProductType = this.productTypes[id];
  },
  
  getProductType: function D_getProductType(id, callback) {
    if(this.productTypes[id] != null) {
      callback(this.productTypes[id]);
      return;
    }
    var self = this;
    this.getData({ptid:id, pid:-1}, function() {
      callback(self.productTypes[id]);
    }, "product_config");
  },
  
  //called from the cart
  selectConfiguredProduct: function D_selectConfiguredProduct(id, doUpdate, doSelect) {
    log("d.selectConfiguredProduct()");
    this.currentCProduct = this.cart.getProduct(id);
    if(this.currentCProduct.product.type.id != this.currentProductType.id) {
      log("changing product type");
      this.currentProductType.deselect();
      this.currentProductType = this.currentCProduct.product.type;
      this.currentProductType.select( function() {
        d.currentProductType.selectConfiguredProduct(d.currentCProduct, doUpdate, doSelect);
      }, d.currentCProduct.product.categoryId, this.currentCProduct.product.id);
    } else {
      this.currentProductType.selectConfiguredProduct(this.currentCProduct, doUpdate, doSelect);
    }
    this.cart.selectCartItem(this.currentCProduct);
    this.currentCProduct.setAlertIcons();
  },
  
  updateConfiguredProductId: function D_updateCurrentConfiguredProductId(oldId, newId) {
    log("updateConfiguredProductId from " + oldId + " to " + newId);
    var cp = this.cart.getProduct(oldId);
    cp.id = newId;
    delete this.cart.productsById[oldId];
    this.cart.productsById[newId] = cp;
    if(this.currentCProduct == cp) {
      log("updateConfiguredProductId: this.currentCProduct == cp");
      //need to regen the fields...
      this.currentProductType.setFields(this.currentCProduct);
    }
  },
  
  updateCancelState: function D_updateCancelState(id, options) {
    var prod = this.cart.getProduct(id);
    if(prod == null) { //dynamically added derived object... (digitization)
      prod = new ConfiguredProduct(id, options);
			this.cart.add(prod);
    } else {
      prod.options = options;
    }
  },
  
  // Find the first view/area that has the selected
  initViews: function D_initViews(defaultView){
    //log("initViews:");
    //init the base price to include the first area price that can use the selected process
    for(var i =0; i < this.currentCProduct.product.views.list.size(); i++) {
      var pView = this.currentCProduct.product.views.list[i];
      log("-View:"); log(pView) ;
      for(var j=0; j < pView.areas.list.size(); j++) {
        var pArea = pView.areas.list[j] ;
        log("--Area: "); log(pArea);
        for(var k=0; k < pArea.processes.list.size(); k++) {
          var allowed_p = pArea.processes.list[k];
          if (allowed_p.id == d.userSelectedProcessId) {
            d.selectCurrentView(pView.id, pArea.id) ;
            return;
          }
        }
      }
    }
    
  },
  
  //load the product view 
  selectCurrentView: function D_selectCurrentView(id, areaId) {
    log("selectCurrentView()");
    this.viewToggle(id); //make it appear selected
    if(this.currentCView != null) {
      this.currentCView.hide();
    }
    //this.currentView = this.currentProduct.views.byId[id];
    this.currentCView = this.currentCProduct.getView(id, true);
    //this.currentCView.setDesignerBackground(); show() will do this
    
    if(this.mode != DESIGNER_MODE_VIEW_CUSTOM_PRODUCT) { //lets also set the area and load the items used in that area
      
      if(areaId == null) { //no area passed... get the first used area.. if none used get the first area...
        areaId = this.currentCView.getFirstAreaId();
        if(areaId==null) {
          log("selectCurrentView: ERROR: no first area in view");
        }
      } else {
        log("selectCurrentView: using passed areaId:" + areaId);
      }
      this.currentCView.show();
      
      
      this.selectCurrentArea(areaId, false);
      this.currentCView.setBgPosition();
    } else {
      this.currentCView.show();
      this.currentCView.checkBgImage();
    }
  },
  
  selectCurrentArea: function D_selectCurrentArea(areaId, allowTransition, fromMouseClick) {
    this.currentCViewArea = this.currentCView.getArea(areaId, true);
    log("d.selectCurrentArea(" + this.currentCViewArea.productArea.name + ")");
    var rb = $("a_sel_" + areaId);
    if(rb != null) {
      rb.checked = true;
    }
    this.currentCViewArea.show(allowTransition);
    if(this.currentCViewArea.canZoom()) {
      if(fromMouseClick && this.currentCanvasType == 0 && this.designerOptions.clickAreaZooms()) {
        this.setZoomEnabled(this.currentCViewArea, true, false);
        d.selectTab('d','design', function(tab) { return d.selectDesignTab(tab, true); });
      } else {
        this.setZoomEnabled(this.currentCViewArea, true, (this.currentCanvasType == 1));
      }
    } else { //if(this.currentCanvasType == 1) {
      this.setZoomEnabled(this.currentCViewArea, false, true);
    }
    this.checkCopyPasteState();
  },
  
  checkAreaHighlightPosition: function D_checkAreaHighlightPosition(viewId) {
    if(this.currentCView != null && this.currentCView.id == viewId) {
      log("checkAreaHighlightPosition(" + viewId + ");");
      this.currentCView.positionAreaHighlight();
    } else if(this.currentCView == null) {
      log("checkAreaHighlightPosition: currentCView is null");
    } else {
      log("checkAreaHighlightPosition: currentCView.id (" + this.currentCView.id + ") <> " + viewId);
    }
  },
  
  selectCurrentProcess: function D_selectCurrentProcess(processId) {
   log("depricated call to selectCurrentProcess", true);
  },
  
  /*
  when viewing a product outside the designer
  */
  initViewMode: function D_initViewMode() {
    //this.currentProductType.selectConfiguredProduct(this.currentProduct, true, false);
  },
  
  //check if in ammend mode and trying to do something that could modify the price...
  canAddAsset: function D_canModifyDesign(processId) {
    if(this.mode == DESIGNER_MODE_AMEND) {
      var cpvap = this.currentCViewArea.processes[processId];
      if(cpvap.items.list.length == 0) { //about to add
        return false;
      }
      return cpvap.productProcess.canModifyDesign();
    }
    return true;
  },
  
  addImage: function D_addImage(processId) {
    if(processId == null) {
      //select process
      processId = this.showSelectProcess("image");
      if(processId == null) {
        return;
      }
    }
    if(!this.canAddAsset(processId)) {
      alert(ml("You cannot add an image to this area because it would change the price of your order"));
      return;
    }
    this.newProcessId = processId;
    
    
    this.decorationLibraryManager.selectImage(this.currentCViewArea.productArea.processes.byId[processId], function(image) {
        var newAsset = d.addAsset(image.assetOptions());
        if((this.mode == DESIGNER_MODE_AMEND) && (newAsset.hasCost())) {
          if(newAsset.imageType == 2) {
            alert(ml("You cannot add this embroidery design because it would change the price of your order."));
          } else {
            alert(ml("You cannot add this image design because it would change the price of your order."));
          }
          return;
        }
        
        
        var opts = {ar:"1"};
        if(newAsset.imageType == 2) {
          opts.emb="1";
          opts.stc = newAsset.stitchCount;
          opts.cw = newAsset.colorWays.length > 0 ? 0 : null;
        } 
        var process = processes.byId[this.newProcessId];
        if(newAsset.imageType != 2 && process.isWilcomEMB() && newAsset.digitizedProcessId != process.id) { //we are adding a non emb to a wilcom area... make sure its ready for it...
          log("Adding undigited image to embroidery area");
          if(process.autoSplit) { //fulfillment house setup to auto reduce/split colors 
            opts.cc = process.maxColors;
            opts.spc = "1" ;
            popup("split_colors_status");
            var self = this;
            var ajax = new Ajax.Request(d.ajaxUrl("/shared/library/digitize_asset/" + newAsset.id + "?color_count=" + process.maxColors + "&process_id=" + process.id), {asynchronous:true, evalScripts:true, 
                onSuccess: function D_onSuccess(transport) {
                  var result = transport.responseText.evalJSON();
                  log(result);
                  newAsset = d.addAsset(result);
                  var existingColors = newAsset.getMetaData(["split_colors", process.maxColors], null);
                  //var merged = hashMerge(existing, result);
                  //newAsset.setMetaData(["split_colors", process.maxColors], merged);
                  log(newAsset);
                  //init the items colors
                  opts.c = existingColors.process_colors[self.newProcessId].join(":");
                  self.addNewItemByAsset(self.newProcessId, newAsset, opts);
                  self.decorationLibraryManager.getLibrary(self.newProcessId, function(decLib) {
                      decLib.myDigitizedDesigns.toggleVisible(true);
                      if(decLib.myDigitizedDesigns.selected) {
                        decLib.myDigitizedDesigns.refreshImages(true);
                      } else {
                        decLib.myDigitizedDesigns.select();
                      }
                  });
                },
                onFailure: function D_onFailure(transport) {
                  alert("An Error Occured:" + transport.responseText);
                },
              //  onException: function D_onException() {
            //      alert("Exception occured");
              //  },
                onComplete: function D_onComplete() {
                  closePopup("split_colors_status");
                }
            });
            
            /*
            this.image.getPercentOpaque(function(percent) {
                this.selectImageCallback(this.image);
                this.close();
            }.bind(this));
            */
            return;
          } else {
            
            popup("copy_digitize_image");
            var self = this;
            var ajax = new Ajax.Request(d.ajaxUrl("/shared/library/make_digitize_copy/" + newAsset.id + "?process_id=" + process.id), {asynchronous:true, evalScripts:true, 
                onSuccess: function(transport) {
                  var result = transport.responseText.evalJSON();
                  log(result);
                  newAsset = d.addAsset(result);
                  newAsset.getOpacity(null, function(percent) {
                      closePopup("copy_digitize_image");
                      newAsset.setMetaData("percent_opaque", percent);
                      opts.po = percent;
                      self.addNewItemByAsset(self.newProcessId, newAsset, opts);
                      self.decorationLibraryManager.getLibrary(self.newProcessId, function(decLib) {
                          decLib.myDigitizedDesigns.toggleVisible(true);
                          if(decLib.myDigitizedDesigns.selected) {
                            decLib.myDigitizedDesigns.refreshImages(true);
                          } else {
                            decLib.myDigitizedDesigns.select();
                          }
                      });
                  });
                },
                onFailure: function(transport) {
                  closePopup("copy_digitize_image");
                  alert("An Error Occured:" + transport.responseText);
                }
            });
            return;
          }
        } else if(newAsset.imageType != 2 && process.isWilcomEMB()) { //its a digitized asset..          
          if(process.autoSplit) { //fulfillment house setup to auto reduce/split colors 
            var existingColors = newAsset.getMetaData(["split_colors", process.maxColors], null); //get the existing colors...
            if(existingColors != null) { 
              opts.c = existingColors.process_colors[process.id].join(":");
              opts.cc = process.maxColors;
              opts.spc = "1" ;
            }
          }
        }
        this.addNewItemByAsset(this.newProcessId, newAsset, opts);
    }.bind(this));
    d.track("add-image");
    return;
  },
  
  addText: function D_addText(processId) {
    if(processId == null) {
      processId = this.showSelectProcess("text");
      if(processId == null) {
        return;
      }
    }
    if(!this.canAddAsset(processId)) {
      alert(ml("You cannot add an image to this area because it would change the price of your order"));
      return;
    }
    this.newProcessId = processId;
    $("new_text").value = "";
    popup("new_text_popup");
    $("new_text").focus();
  },
  
  addTeamName: function D_addText(processId) {
    if(processId == null) {
      processId = this.showSelectProcess("text");
      if(processId == null) {
        return;
      }
    }
    //check there is not already a teamname (if EMB)
    if(processes.byId[processId].isWilcomEMB()) {
      if(this.currentCViewArea.processes[processId].isUsingItemOfType(2)) {
        alert(ml("You can only have 1 embroidery teamname per decoration area"));
        return;
      }
    }
    
    this.newProcessId = processId;
    $("teamname_templates_container").update(this.teamNameTemplates.buildHtml(processId));
    
    var sizeHtml = "";
    if(this.currentProductType.sizeField != null) {
      sizeHtml = '<h4>' + ml('Setup Sizing (can be changed later)') + '</h4>' + this.currentProductType.sizeField.renderMultiQty(this.currentCProduct, this.currentCProduct.product.getSizeField(), this.currentCProduct.getSelectedSize(), this.currentCProduct.product.sizeColorCombinations, "tn_", false, true);
    } else {
      sizeHtml = '<h4>' + ml('Select Qty (can be changed later)') + '</h4>' + ml('Number of teamnames') + ': <input type="text" size="3" id="tn_qty" value="' + this.currentCProduct.qty + '"/>';
    }
    $("teamname_sizing_container").update(sizeHtml);
    popup("new_teamname_popup");
  },
  
  
  continueAddTeamname: function() {
    var opts = {team_t: this.teamNameTemplates.selectedTemplateId};
    var proc = processes.byId[this.newProcessId];
    if(proc.isWilcomEMB()) {
      opts.emb = "1";
    }
    opts.tc = pwColorPicker.getDefaultColor(this.newProcessId, "#FF3333", proc.defaultTextColorId);
    var teamItem = this.addNewItemByAsset(this.newProcessId, new TeamNameAsset(), opts);
    
    if(this.currentCProduct.getTeamNames().initNew(teamItem)) {
      popup("edit_teamname_popup");
    } else {
      alert(ml("You specify the number of teamnames you want"));
    }
  },
  
  //get a list of allowed item types (image/text/teamname) by process
  getAllowedItemTypes: function D_getAllowedItemTypes() {
    if(this.allowedItemTypes != null) {
      return this.allowedItemTypes;
    }
    var allowed = {
      image: { count:0, single:null},
      text: { count:0, single:null},
      teamname: { count:0, single:null}
    };
    for(var i=0; i < processes.list.length; i++) {
      var proc = processes.list[i];
      if(proc.allowImages) {
        allowed.image.count ++;
        allowed.image.single = proc.id;
      }
      if(proc.allowText) {
        allowed.text.count ++;
        allowed.text.single = proc.id;
      }
      if(proc.allowTeamNames) {
        allowed.teamname.count ++;
        allowed.teamname.single = proc.id;
      }
    }
    this.allowedItemTypes = allowed;
    return this.allowedItemTypes;
  },
  
  //when an area/process is selected check what add item options should be available...
  checkAddAvailableOptions: function D_checkAddAvailableOptions() {
    var allAllowed = this.getAllowedItemTypes();
    
    if(allAllowed.image.count == 0) {
      //$("no_items_0_image").hide();
      $("add_item_image").hide();
    } else {
      //$("no_items_0_image").show();
      $("add_item_image").show();
    }
    if(allAllowed.text.count == 0) {
      //$("no_items_0_text").hide();
      $("add_item_text").hide();
    } else {
      //$("no_items_0_text").show();
      $("add_item_text").show();
    }
    if(allAllowed.teamname.count == 0) {
      //$("no_items_0_teamname").hide();
      $("add_item_team_name").hide();
    } else {
      //$("no_items_0_teamname").show();
      $("add_item_team_name").show();
    }
  },
  
  showSelectProcess: function D_showSelectProcess(type) {
    var types = ["text","teamname","image"];
    for(var i=0; i < types.length; i++) {
      if(types[i] == type) {
        $("select_type_" + types[i]).show();
      } else {
        $("select_type_" + types[i]).hide();
      }
    }
    //$("select_type_" + type).style.display = "";
    //$("select_type_" + otherType).style.display = "none";
    
    var allowedProcesses = this.currentCViewArea.getAllowedProcesses();
    var allowedTypes = this.getAllowedItemTypes();
    
    //if(allowedTypes[type].count == 1) {
    //  return allowedTypes[type].single;
    //}
    
    var procSize = hashSize(allowedProcesses);
    if(procSize == 0) {
      alert(ml("This product has been configured incorrectly and has no usable decoration processes assigned to it."));
      return null;
    } else {
      for(var i=0; i < processes.list.size(); i++) {
        var process = processes.list[i];
        /*if(process.allow[type] == true) { //can this process allow this type (i.e can emb allow text?)
          $("add_" + type + "_type_" + process.id).show();
        } else {
          $("add_" + type + "_type_" + process.id).hide();
        }*/
        
        if((allowedProcesses[process.id])&&(process.allow[type] == true)) { //we can use the process....
          $("add_" + type + "_type_" + process.id).className="";
        } else {
          $("add_" + type + "_type_" + process.id).className="disabled";
          //why cant we add this?
          if(process.allow[type] != true) {
            if(type=="text") {
              $("add_item_" + type + "_disabled_" + process.id).update(ml("Unable to use %s because it cannot be have text added", process.name));
            } else if(type=="teamname") {
              $("add_item_" + type + "_disabled_" + process.id).update(ml("Unable to use %s because it cannot be have team names added", process.name));
            } else if(type=="image") {
              $("add_item_" + type + "_disabled_" + process.id).update(ml("Unable to use %s because it cannot be have image designs added", process.name));
            }
          } else if(this.currentCViewArea.productArea.canDecorate(process)) { //because of mixing
            $("add_item_" + type + "_disabled_" + process.id).update(ml("Unable to use %s because it cannot be mixed with existing decorations", process.name));
          } else {
            $("add_item_" + type + "_disabled_" + process.id).update(this.currentCViewArea.productArea.getDecProcDisabledMessage(process));
          }
          
        }
      }
      popup("select_type_popup");
      return null;
    }
  },
  
  continueAddText: function D_continueAddText() {
    var text = $("new_text").value;
    if((text == null)||(text == "")) {
      alert(ml("You must enter a value"));
      return;
    }
    var opts = {text: text};
    var proc = processes.byId[this.newProcessId];
    if(proc.isWilcomEMB()) {
      opts.emb = "1";
    }
    opts.tc = pwColorPicker.getDefaultColor(this.newProcessId, "#FF3333", proc.defaultTextColorId);
    this.addNewItemByAsset(this.newProcessId, new TextAsset(), opts);
  },
  
  addNewItemByAsset: function D_addNewItemByAsset(processId, asset, initData) {
    //add to current canvas
    var newItem = this.currentCViewArea.addNewItem(processId, asset, initData);
    if(newItem != null) { 
      newItem.select();
      d.itemChanged(true);
      return newItem;
    }
  },
  
  startNewCartItem: function D_startNewCartItem(doSelect, showTab) {
    var cp = this.cart.getUnsavedProduct();
    if(cp != null) {
      this.selectConfiguredProduct(cp.id, true, doSelect);
      if(showTab) {
        d.selectTab('m','apparel');
      }
      cp.setAlertIcons();
    } else {
      
      var asyncKey = asyncStart("designer_container");
      var self = this;
      var t2 = new Ajax.Request(d.ajaxUrl(d.pathPrefix + "/designer/new_product?id=" + this.currentCProduct.product.id), {asynchronous:true, evalScripts:true, onComplete: function D_onComplete(response) {
          asyncFinish(asyncKey);
          cp = self.cart.getUnsavedProduct();
          if(cp != null) {
            self.selectConfiguredProduct(cp.id, true, doSelect);
            if(showTab) {
              d.selectTab('m','apparel');
            }
            cp.setAlertIcons();
          } else {
            alert("ERROR: No new item was added");
          }
        }
       });
    }
    
  },
  
  tbTransformed: function D_tbTransformed(configuredProductId, viewId, areaId, options) {
    var cp = this.cart.getProduct(configuredProductId);
    if(cp == null) {
      log("tbTransformed: Unable to get configured product " + configuredProductId);
      return;
    }
    var view = cp.views[viewId];
    if(view == null) {
      log("tbTransformed: Unable to get view " + viewId);
      return;
    }
    var area = view.areas[areaId];
    if(area == null) {
      log("tbTransformed: Unable to get area " + areaId);
      return;
    }
    area.tbTransformed(options);
  },
  
  selectTab: function D_selectTab(type, tab, callback) {
    var curTab = this.selected_tabs[type];
    if(curTab == tab) {
      return;
    }
    d.deSelectCurrentItem();
    d.track("select-tab/" + type + "/" + tab);
    
    if(callback!=null) {
      if(!callback(tab)) {
        return;
      }
    }
    log("cur tab = " + curTab + " type=" + type);
    var oldTab = $(type + "_" + curTab);
    if(oldTab.className != "unselected_tab_hidden") {
      $(type + "_" + curTab).className = "unselected_tab";
    }
    $(type + "_" + tab).className = "selected_tab";
    
    if(callback==null) {
      $(type + "_" + curTab + "_pane").style.display = "none";
      $(type + "_" + tab + "_pane").style.display = "";
    }
    this.selected_tabs[type] = tab;
    
    if(type=="m") {
      //if(tab=="customize") {
      //  this.refreshGallery();
      //}
      /*if(tab=="cart") {
        $("not_cart").style.display="none";
        $("is_cart").style.display="";
      } else {
        $("not_cart").style.display="";
        $("is_cart").style.display="none";
      }*/
    }
  },
  
  selectDesignTab: function D_selectDesignTab(tab, autoZoomed) {
    if(d.mode==DESIGNER_MODE_VIEW_CUSTOM_PRODUCT) {
      setBackgroundImage(d.designPane, d.designPane, this.currentCProduct.getViewURL(this.currentLayout.id, 1));
      return;
    }
    if(!this.currentCViewArea.canZoom()) {
      this.setZoomEnabled(this.currentCViewArea, false, false);
      return;
    }
    log("selectDesignTab");
    if(tab == null) {
      if(this.currentCanvasType == 0) {
        tab = "layout";
      } else {
        tab = "design";
      }
    }
    if(tab=="layout") {
      this.currentCanvasType = 0;
      if($("zoom_out_button").style.display != "none") {
        this.displayZoomButton(false);
      }
    } else {
      this.currentCanvasType = 1;
      if(d.designerOptions.clickAreaSelects() && this.designerOptions.clickAreaZooms() && this.currentCViewArea.canZoom()) {
        this.displayZoomButton(true);
      }
    }
    
    this.currentCView.toggleDesignMode();
    //this.calibrateCanvas(true);
    return true;
  },
  
  displayZoomButton: function D_displayZoomButton(show) {
    if(this.zoomButtonEffect != null) {
      this.zoomButtonEffect.cancel();
      this.zoomButtonEffect = null;
    }
    if(!show) {
      if($("zoom_out_button").style.display != "none") {
        this.zoomButtonEffect = Effect.Fade("zoom_out_button", { duration: 1.0 });
      }
    } else {
      this.zoomButtonEffect = Effect.Appear("zoom_out_button", { duration: 1.0 });
    }
  },
  
  setZoomEnabled: function D_setZoomEnabled(area, enabled, toggleZoomButton) {
    if(enabled) {
      if(this.currentCanvasType == 0) { //zoomed out
        $("d_layout").className = "selected_tab";
        $("d_design").className = "unselected_tab";
      } else {
        $("d_layout").className = "unselected_tab";
        $("d_design").className = "selected_tab";
      }
      updateToolTip("d_layout", ml("Zoom out to display the complete product"));
      updateToolTip("d_design", ml("Zoom into the decoration area to get better control"));
      if(toggleZoomButton) this.displayZoomButton(true);
    } else {
      $("d_layout").className = "selected_tab";
      $("d_design").className = "selected_tab";
      updateToolTip("d_layout", ml("Unable to zoom because this decoration area is too large"));
      updateToolTip("d_design", ml("Unable to zoom because this decoration area is too large"));
      if(toggleZoomButton) this.displayZoomButton(false);
    }
  },
  
  calibrateCanvas: function D_calibrateCanvas(fromSwitch) {
    //var pos = Position.cumulativeOffset(this.currentCanvas);
    //this.canvasX = pos[0];
    //this.canvasY = pos[1];
  },
  
  //store what zoom level we are currently using...
  setCurrentZoom: function(zoom) {
    this.zoom = zoom;
  },
  
  toCanvasDims: function D_toCanvasDims(dims, productProcess, canvasType) {
    if(productProcess==null) {
      alert("Error: toCanvasDims: productProcess==null");
    }
    //log(productProcess);
    //log(dims);
    var scale = 1.0;
    if(canvasType!=null) {
      scale = (canvasType==0) ? productProcess.layoutScale : productProcess.designScale;
    } else {
      scale = productProcess.layoutScale * this.zoom;
    }
    if(dims.l != null) {
      dims.l = (dims.l * scale);// + this.canvasX;
    }
    if(dims.t != null) {
      dims.t = (dims.t * scale);// + this.canvasY;
    }
    if(dims.h != null) {
      dims.h = (dims.h * scale);
    }
    if(dims.w != null) {
      dims.w = (dims.w * scale);
    }
    return dims;
  },
  
  fromCanvasDims: function D_fromCanvasDims(dims, productProcess, canvasType) {
    if(productProcess==null) {
      alert("Error: fromCanvasDims: productProcess==null");
    }
    var scale = 1.0;
    if(canvasType!=null) {
      scale = (canvasType==0) ? productProcess.layoutScale : productProcess.designScale;
    } else {
      scale = productProcess.layoutScale * this.zoom;
    }
    if(dims.l != null) {
      dims.l = (dims.l) / scale;
    }
    if(dims.t != null) {
      dims.t = (dims.t) / scale;
    }
    if(dims.h != null) {
      dims.h = (dims.h / scale);
    }
    if(dims.w != null) {
      dims.w = (dims.w / scale);
    }
    return dims;
  },
  
  viewMouseMove: function D_viewMouseMove(td) {
    if(td.className != "d_layout_selected") {
      td.className = "d_layout_mouseover";
    }
  },
  
  viewMouseOut: function D_viewMouseOut(td) {
    if(td.className != "d_layout_selected") {
      td.className = "d_layout_unselected";
    }
  },
  
  viewClick: function D_viewClick(viewId) {
    if(viewId == this.selectedViewId) {
      return;
    }
    this.selectCurrentView(viewId);
  },
  
  //toggle the 'selected' class on the thumbnail of the view
  viewToggle: function D_viewToggle(viewId) {
    if(viewId == this.selectedViewId) {
      return;
    }
    var td = $("d_l_" + this.selectedViewId);
    if(td!=null) {
      td.className = "d_layout_unselected";
    }
    td = $("d_l_" + viewId);
    if(td!=null) {
      td.className = "d_layout_selected";
    }
    this.selectedViewId = viewId;
  },
  /*
  layoutSelect: function D_layoutSelect(el, layoutId) {
    this.currentCProduct.layoutSelect(layoutId, el.checked);
  },
  */
  layoutChecked: function D_layoutChecked(el, id) {
    if(!el.checked) {
      if(this.currentCProduct.layoutExistsWithItems(id)) {
        if(confirm(ml("Are you sure you want to remove all the designs?"))) {
          var lm = this.currentCProduct.views[id];
          while( lm.items.length> 0) {
            lm.items[0].del();
          }
          lm.selected = false;
          this.itemChanged(true);
        }
      }
    }
  },
  
  colorMouseMove: function D_colorMouseMove(t, id) {
    //if(t.className != "color_panel_cell_selected") {
      //t.className = "color_panel_cell_over";
    //}
    t.className=t.className.replace(" over", "");
    t.className=t.className+" over";
  },
  
  colorMouseOut: function D_colorMouseOut(t, id) {
    //if(t.className != "color_panel_cell_selected") {
      //t.className = "color_panel_cell";
    //}
    t.className=t.className.replace(" over", "");
  },
  
  piMouseMove: function D_piMouseMove(t, id) {
    if(t.className != "product_cell_selected") {
      t.className = "product_cell_over";
    }
  },
  
  piMouseOut: function D_piMouseOut(t, id) {
    if(t.className != "product_cell_selected") {
      t.className = "product_cell";
    }
  },
  
  getNextId: function D_getNextId() {
    return this.nextId --;
  },
  
  getNextItemId: function CP_getNextItemId() {
    return this.nextItemId ++; 
  },
  
  registerServerItemId: function CP_registerServerItemId(id) {
    if(id >= this.nextItemId) {
      this.nextItemId = id + 1;
    }
    return id;
  },
  
  qtyChanged: function D_qtyChanged(fromKeyUp) {
    if(fromKeyUp && !this.currentCProduct.product.usesMinQty()) {
      this.currentCProduct.updateQty($("qty").value, false);
      d.itemChanged();
    } else if(!fromKeyUp && this.currentCProduct.product.usesMinQty()) {
      this.currentCProduct.updateQty($("qty").value, false);
      d.itemChanged();
    }  
  },
  
  multiQtyChange: function D_multiQtyChange(el, fieldId, optionId, subOptionId) {
    this.currentCProduct.updateMultiQty(el.value, fieldId, optionId, subOptionId);
    d.itemChanged();
  },
  
  //user had clicked the dropdown for qty
  qtyDropDown: function D_qtyDropDown() {
    if(this.qtyDropDownActive) {
      //ignore.. mouseup will hide the dropdown...
    } else {
      $("qty_dropdown_float").update(this.currentCProduct.product.buildQtyDropdownHtml(this.currentCProduct.qty));
      $("qty_dropdown_float").show();
      this.qtyDropDownActive=true;
      //$("qty_selector_sprites").style.top = "-66px";
	  $("qty_selector").className="alt";
	  
      this.qtyDropDownTime = new Date().getTime();
      Event.observe(document.body, "mouseup", this.onQtyDDBgEvent);
    }
  },
  
  qtyDropDownSelected: function D_qtyDropDownSelected(qty) {
    $("qty").value = qty;
    this.currentCProduct.updateQty(qty, false);
    d.itemChanged();
  },
  
  onQtyDDBg: function D_onQtyDDBg(event) {
    var thisTime = new Date().getTime();
    if(this.qtyDropDownTime != null && thisTime - this.qtyDropDownTime < 2000) {
       this.qtyDropDownTime = null;
       return; //this was the mouse up event from when we bound it... we ignore it....
    }
    //$("qty_selector_sprites").style.top = "-22px";
	$("qty_selector").className=null;
	
    $("qty_dropdown_float").hide();
    this.qtyDropDownActive = false;
    Event.stopObserving(document.body, "mouseup", this.onQtyDDBgEvent);
  },
  
  fieldChange: function D_fieldChange(el, fieldId) {
    d.currentCProduct.setFieldValue(fieldId, parseInt($(el).value, 10)) ;
  },
  
  itemChanged: function D_itemChanged(is_layout_change) {
    if(is_layout_change) {
      this.currentCProduct.onLayoutChanged();
      this.currentCView.queueViewUpdate();
      $("save_div").style.display="";
    }
    this.currentCProduct.product.type.itemChanged();
  },
  
  //from server callback to let us know a thumbnail for a view is ready...
  updateView: function D_updateView(cpid, viewId, src, renderVersion, results) {
    var p = this.cart.getProduct(cpid);
    if(p!=null) {
      p.updateView(viewId, src, renderVersion, results);
    }
  },
  
  checkout: function D_checkout() {
    if(d.mode == DESIGNER_MODE_AMEND) {
      window.location = d.pathPrefix + "/user/view_order/" + this.cart.id + this.extraExternalParams;
    } else {
      if($("update_cart_container") != null) {
        if($("update_cart_container").style.display == "") {
          if(!confirm(ml("You have unsaved changes to the current item in your cart. Are you sure you want to checkout with saving?"))) {
            return;
          }
        }
      }
      d.track("checkout");
      proceedWithOrder();
      //window.location = d.pathPrefix + "/shop/verify" + this.extraExternalParams;
      
    }
  },
  
  notifyCartChanged: function D_notifyCartChanged() {
    if(window.opener != null) {
      try {
        window.opener.notifyCartChanged();
      } catch(e) {
        log("Unable to notify opener window of item saved");
        log(e);
      }
    }
  },
  
  offsetTop: function D_offsetTop(element, cutOff) {
    var valueT = 0;
    do {
      valueT += element.offsetTop  || 0;
      element = element.offsetParent;
    } while (element && element != cutOff);
    return valueT;
  },
  
  scrollCat: function D_scrollCat(amount) {
    this.currentProductType.scrollCat(amount);
  },
  
  showQualityWarning: function D_showQualityWarning() {
    if(this.hideQualityWarning) {
      return false;
    }
    //popup('quality_warning');
    //return true;
    return false;
  },
  
  acceptQualityWarning: function D_acceptQualityWarning() {
    var doHide = $("dont_show_qual_warning").checked;
    if(doHide) {
      this.hideQualityWarning = true;
      var t2 = new Ajax.Request(d.ajaxUrl(d.pathPrefix + "/designer/user_quality_warning"), {asynchronous:true, evalScripts:true });
    }
    closePopup('quality_warning');
  },
  
  //user has selected a different product type....
  changeProductType: function D_changeProductType(el) {
    var pt = el.value;
    
    if(pt != this.currentProductType.id) {
      this.deSelectCurrentItem();
      
      d.track("change-product-type");
      
      this.currentProductType.deselect();
      var self = this;
      
      this.getProductType(pt, function(prodType) {
        self.currentProductType = prodType;
        if (self.currentProductType.id == $("sel_prod_type").value) {
          self.currentProductType.select( function() {
            d.currentProductType.selectConfiguredProduct(d.currentCProduct, true, false);
            d.currentCProduct.afterProductChanged();
          }, -1, -1);
        }
        //$("product_type_tab_name").innerHTML = prodType.name;
      });
      
    }
    
  },
  
  recalibrateCanvas: function D_recalibrateCanvas() {
    if(this.currentCViewArea!=null) {
      this.currentCViewArea.canvasX = null;
      if(this.currentCViewArea.selectedItem != null) {
        this.currentCViewArea.selectedItem.autoRepositionHandles();
      }
    }
  },
  
  roundPrice: function D_roundPrice(price) {
    if(this.priceRounding > 1) {
      log("rounding " + price + " to " + this.priceRounding);
      var cents = Math.round(price * 100);
      log("cents = " + cents);
      var divs = parseInt(cents / this.priceRounding, 10);
      log("divs = " + divs);
      var adjCents = divs * this.priceRounding;
      log("adjCents = " + adjCents);
      if(adjCents < cents) {
        log("adjCents < cents");
        adjCents += this.priceRounding;
      }
      //round to 99cents if on 1 dollar
      if(this.price99) {
        if((adjCents % 100 == 0)&&(cents>0)) {
          log("adjCents % 100");
          adjCents -= 1;
        }
      }
      price = parseFloat(adjCents) / 100;
    }
    return price;
  },
  
  formatPrice: function D_formatPrice(price, clazz, applyTax) {
    if(applyTax==null) {
      applyTax = true;
    }
    var taxWarn = "";
      if((this.tMod != 1)&&(applyTax) && !d.currentCProduct.product.taxExempt) {
      log("Applying tax mod of " + this.tMod);
      taxWarn = '<span class="tax_warning">*</span>';
      price *= this.tMod;
    }
    price *= this.cMod;
    var dc = price.toFixed(2);
    var codeHtml = this.curCode;
    if(clazz!=null) {
      codeHtml = '<span class="' + clazz + '">' + this.curCode + "</span>";
    }
    
    switch(this.priceFormat) {
      case 1: return this.curGlyph + dc + " " + taxWarn;
      case 2: return dc + " " + codeHtml + taxWarn;
      case 3: return dc + " " + taxWarn;
      case 4: return dc + this.curGlyph + " " + taxWarn;
      default: return this.curGlyph + dc + " " + codeHtml + taxWarn;
    }
  },
  
  deSelectCurrentItem: function D_deSelectCurrentItem() {
    if(this.currentCViewArea) {
      log("deSelectCurrentItem");
      this.currentCViewArea.selectItem(null);
    }
  },
  
  onKeyUp: function D_onKeyUp(event) {
    if(this.currentCViewArea && this.currentCViewArea.selectedItem!=null) {
      if(event==null) {
        event = window.event;
      }
      if(event.keyCode==Event.KEY_DELETE) {
        var el = Event.element(event);
        
        var allowDelete = true;
        
        while(el != null) {
          if(el.tagName == "INPUT" || el.tagName == "SELECT" || el.tagName == "TEXTAREA") {
            return;
          } else if(el.getAttribute("allow-delete") == "true") {
            return;
          }
          el = el.parentElement;
        }
        if(this.currentCViewArea.selectedItem.canModifyDesign) {
          this.currentCViewArea.selectedItem.deleteClick(event);
        }
      }
    }
  },
  
  showProductInfo: function D_showProductInfo() {
      d.deSelectCurrentItem();
      var purl = "/ppr/product_info/ppop";
      var url = "";
      if(purl.indexOf("?") == -1) {
        url = purl + "?pid=" + this.currentCProduct.product.id;
      } else {
        url = purl + "&pid=" + this.currentCProduct.product.id;
      }
    //}
    $("dynamic_popup").innerHTML = "<br/><br/>Generating..<br/><br/>";
    var aKey = null;
    var t2 = new Ajax.Updater({success:"dynamic_popup"}, d.ajaxUrl(url), {asynchronous:true, evalScripts:true,
      onComplete: function D_onComplete() { 
        asyncFinish(aKey);
		$$("#dynamic_popup .popup")[0].style.width="650px";
      },
      onSuccess: function D_onSuccess() {
        repositionPopup("dynamic_popup");
		
      },
      onFailure: function D_onFailure() {
        closePopup("dynamic_popup");
        alert("An error occured processing preview");
      }
    });
    
    popup("dynamic_popup");
    aKey = asyncStart($("dynamic_popup"));
  },
  showDesignerHelp: function D_showDesignerHelp() {
      d.deSelectCurrentItem();
      var url = "/ppr/product_info/designer_help/ppop?popup";
    $("dynamic_popup").innerHTML = "<br/><br/>Generating..<br/><br/>";
    var aKey = null;
    var t2 = new Ajax.Updater({success:"dynamic_popup"}, d.ajaxUrl(url), {asynchronous:true, evalScripts:true,
      onComplete: function D_onComplete() { 
        asyncFinish(aKey);
		$$("#dynamic_popup .popup")[0].style.width="550px";
		$("dynamic_popup").style.width="550px";
		$("dynamic_popup").style.marginLeft="-275px";
      },
      onSuccess: function D_onSuccess() {
        repositionPopup("dynamic_popup");
		
      },
      onFailure: function D_onFailure() {
        closePopup("dynamic_popup");
        alert("An error occured processing preview");
      }
    });
    
    popup("dynamic_popup");
    aKey = asyncStart($("dynamic_popup"));
  },
  
  displayAssetInformation: function D_displayAssetInformation(asset) {
    $("asset_view").style.display='';
    $("i_no_tab").width="600";
    var aImg = $("asset_view_img");
    var dim = asset.scale(300,300);
    aImg.style.width = parseInt(dim.w, 10) + "px";
    aImg.style.height = parseInt(dim.h, 10) + "px";
    setTransparentImage($("asset_view"), aImg, asset.getWUrl(), function() { repositionPopup('add_image'); });
    if(asset.colors != null) {
      var tr = $("asset_colors_tr");
      while(tr.firstChild != null) {
        tr.removeChild(tr.firstChild);
      }
      for(var i=asset.colors.length-1; i >=0; i--) {
        var color = asset.colors[i];
        
        var td = document.createElement("TD");
        td.innerHTML = '<div class="mp_color_button" style="width:10px;display:inline;margin-right:2px;font-size:8px;height:10px;background-color:' + color + ';cursor:default;"><img src="' + this.pathPrefix + '/images/trans.gif" width="10" height="10" border="0"/></div>';
        tr.appendChild(td);
      }
      
      $("asset_colors").style.display="";
    } else {
      $("asset_colors").style.display="none";
    }
  },
  
  preloadImages: function D_preloadImages() {
    return;
    
    var imgUrl = null;
    if(!this.effectIconsLoaded) {
      this.preloadEffectIndex ++;
      if(imageEffects.size() <= this.preloadEffectIndex) {
        this.effectIconsLoaded = true;
      } else {
        imgUrl = d.pathPrefix + "/images/effects/" + imageEffects[this.preloadEffectIndex][2];
      }
    }
    if((!this.borderIconsLoaded)&&(imgUrl==null)) {
      this.preloadBorderIndex ++;
      if(borderEffects.size() <= this.preloadBorderIndex) {
        this.borderIconsLoaded = true;
      } else {
        var border = borderEffects[this.preloadBorderIndex];
        if(border[0] == 0) {
          imgUrl = d.pathPrefix + "/images/noborder.gif";
        } else {
          imgUrl = d.pathPrefix + "/border/image/" + border[0] + "/thumb-ppr.gif";
        }
      }
    }
    if(imgUrl!=null) {
      var cbimg = document.createElement("IMG");
      $("preload-panel").appendChild(cbimg);
      var callbackDone = false;
  
      var callback = function() {
        if(callbackDone) {
          return;
        }
        callbackDone = true;
        window.setTimeout( function() {
          d.preloadImages();
        }, 100);
      };
      
      cbimg.onload = callback;
      cbimg.onerror = callback;
      cbimg.onabort = callback;
      cbimg.src = imgUrl;
      if(BrowserDetect.browser == "Explorer") {
        if(cbimg.complete) {
          callback();
        }
      }
    }
  },
  
  saveWorkingVersion: function D_saveWorkingVersion() {
    this.currentCProduct.saveWorkingVersion();
  },
  
  
  track: function D_track(key) {
    if(this.useAnalytics) {
      try {
        urchinTracker("/designer-action/" + key);
      } catch(ex) {
        log("Exception tracking " + key);
        log(ex);
      }
    }
  },
  
  monitorSizing: function D_monitorSizing() {
    if(this.testWidthImg == null) {
      this.testWidthImg = $('body-bottom');
      if(this.testWidthImg!=null) {
        this.lastPageWidthTest = Position.cumulativeOffset(this.testWidthImg)[0];
      }
    } else {
      var pos = Position.cumulativeOffset(this.testWidthImg);
      //log("monitorSizing:" + pos[0] + "," + this.lastPageWidthTest);
      if(pos[0]!=this.lastPageWidthTest) {
        this.recalibrateCanvas();
      }
      this.lastPageWidthTest = pos[0];
    }
    
    if(this.testWidthImg != null) {
      var _this = this;
      window.setTimeout( function() {
          _this.monitorSizing();
          
      }, 500);
    } else {
      log("Not monitoring sizing: no body-bottom");
    }
  },
  
  
  emailDesign: function D_emailDesign() {
    this.currentCProduct.email();
  },
  
  sendEmail: function D_sendEmail() {
    var aKey = null;
    var t2 = new Ajax.Request(d.ajaxUrl(d.pathPrefix + "/designer/send_email?mode=" + this.mode), {asynchronous:true, evalScripts:true, parameters:Form.serialize("email_data", true),
      onComplete: function D_onComplete() {
        asyncFinish(aKey);
      }
    });
    aKey = asyncStart($("dynamic_popup"));
  },
  
  displayGrid: function D_displayGrid(isOn) {
    this.showGrid = isOn;
    if(this.showGrid) {
      $("hide_grid").style.display="";
      $("show_grid").style.display="none";
    } else {
      $("hide_grid").style.display="none";
      $("show_grid").style.display="";
    }
    this.currentCView.prepareAreas(false);
  },
  
  showPreview: function D_showPreview() {
    this.currentCProduct.showPreview();
  },
  
  setDiscountStructure: function D_setDiscountStructure(discounts) {
    this.discounts = discounts;
  },
  
  setAffiliateDiscounting: function D_setAffiliateDiscounting(affiliateDiscounting) {
    this.affiliateDiscounting = affiliateDiscounting;
  },
  
  getDiscount: function D_getDiscount(qty, price, cost) {
    var dis = 0;
    for(var i=0; i < this.discounts.size(); i++) {
      if(qty > this.discounts[i].m) {
        log("found discount level at " + this.discounts[i].m + " discount=" + this.discounts[i].d);
        dis = this.discounts[i].d;
      }
    }
    if(dis == 0) {
      return 0;
    }
    log("applying discount of " + dis);
    if(this.affiliateDiscounting) {
      return Math.round(price * dis) / 100.0 * qty;
    } else {
      return Math.round(cost * dis) / 100.0 * qty;
    }
  },
  
  selectBackgroundColor: function D_selectBackgroundColor(processId) {
    this.currentCViewArea.selectBackgroundColor(processId);
  },
  
  setError: function D_setError(cProductId,views, errors) {
    //sort into views/areas
    var errorsByViews = {};
    if(errors==null) errors = [];
    for(i=0; i < views.length;i++) {
      errorsByViews[views[i]] = {areas:{}, errors:{}};
    }
    for(var i=0; i < errors.length; i++ ){
      var error = errors[i];
      var view = errorsByViews[error.v];
      if(error.a == null) {
        //error is against the view...
        view.errors[error.type + error.cause] = error;
      } else {
        if(view.areas[error.a] == null) {
          view.areas[error.a] = {};
        }
        view.areas[error.a][error.type + error.cause] = error;
      }
    }
    var cProduct = this.cart.getProduct(cProductId);
    //call each view...
    for(i=0; i < views.length;i++) {
      var cView = cProduct.getView(views[i]);
      if(cView != null) {
        cView.setErrors(errorsByViews[views[i]]);
      }
    }
  },
  
  getLengthUnit: function D_getLengthUnit() {
    switch (this.lengthUnit)
    {
    case 1:
      return "in";
    case 2:
      return "cm";
    }
  },
  
  convertLengthFromInches: function D_convertLengthFromInches(l) {
    switch (this.lengthUnit)
    {
    case 1:
      return l;
    case 2:
      return l*2.54;
    }
  },
  
  convertLengthToInches: function D_convertLengthToInches(l) {
    switch (this.lengthUnit)
    {
    case 1:
      return l;
    case 2:
      return l/2.54;
    }
  },
  
  allowedFileUploadImageExtensions: function D_allowedFileUploadImageExtensions() {
    var allowed = [];
    var proc = processes.byId[this.decorationLibraryManager.currentProcessId];
    if((this.mode == DESIGNER_MODE_CONFIGURE) && (proc.isWilcomEMB())) {
      allowed = ["emb"];
    } else {
      if(proc.isWilcomEMB()) {
        if(proc.allowImageUpload) {
          allowed = ["jpg", "jpeg", "png" , "gif", "emb", "svg", "eps"];
        } else {
          allowed = ["emb"];
        }
      } else {
        allowed = ["jpg", "jpeg", "png" , "gif", "svg", "eps"];
      }
    }
    return allowed;
  },
  
  //load the popup asking what to add....
  showAddItemIntro: function() {

    var allowedTypes = this.currentCViewArea.getAllAllowedItemTypes();
    
    var passCount =0;
    var itemTypes = ["image","text","teamname"];
    var passedArrows = [];
    for(var i=0; i < itemTypes.length; i++) {
      var type = itemTypes[i];
      if(allowedTypes[type].count > 0) {
        $("opener_" + type).show();
        passedArrows.push($("arrow_" + type));
        passCount += 1;
      } else {
        $("opener_" + type).hide();
      }
    }
    if(passCount==0) {
      alert("FATAL ERROR: this product cannot be decorated");  
    } else if(passCount==1) {
      passedArrows[0].className = "opener_overlay middle";
    } else if(passCount==2) {
      passedArrows[0].className = "opener_overlay top";
      passedArrows[1].className = "opener_overlay bottom";
    } else {
      //starts correctly...
    }
    
    var loc = "";
    if(this.currentCView.productView.areas.list.length == 1) {
      loc = ml("You will be adding a decoration to the %1s of the %2s", [this.currentCView.productView.name , this.currentCProduct.product.name]);
    } else {
      loc = ml("You will be adding a decoration to the %1s %2s of the %3s", [this.currentCView.productView.name, this.currentCViewArea.productArea.name, this.currentCProduct.product.name]);
    }
    $("opener_location").update(loc);
    
    var self = this;
    popup('opener', {
        bgClass:"lightbg",
        bgOpacity: 0.65,
        positionCallback: function(div) {
           var pos = Position.cumulativeOffset(self.currentCViewArea.canvas);
           var topSectionHeight = $("opener_top_section").getHeight();
           
           div.style.left = (pos[0] + 194 + (self.currentCViewArea.canvas.getWidth() / 2)) + "px";
           
           var top = pos[1] - topSectionHeight - 90 + (self.currentCViewArea.canvas.getHeight() / 2);
           if(top < 10) {
             top = 10;
           }
           div.style.top = top + "px";
           if(self.contentTopEl != null) {
             pos = Position.cumulativeOffset(self.contentTopEl);
             if(pos[1] > top) { //the popup goes above the content top...
               self.contentTopEl = div;
             }
           } else {
             self.contentTopEl = div;
           }
        }
    });
  },
  
  initScrollPosition: function() {
    if(this.contentTopEl != null) {
      this.contentTopEl.scrollIntoView(true);
    }
  },
  
   //user had clicked the dropdown for copy
  chooseCopy: function D_chooseCopy() {
    if(this.copyDropDownActive) {
      //ignore.. mouseup will hide the dropdown...
    } else {
     
      
      $("copy_dropdown_float").show();
      this.copyDropDownActive=true;
      //$("qty_selector_sprites").style.top = "-66px";
      this.copyDropDownTime = new Date().getTime();
      Event.observe(document.body, "mouseup", this.onCopyBgEvent);
    }
  },
  
  copyArea: function D_copyArea() {
    if(hashFirstElement(this.currentCViewArea.allItems) != null) {
      this.hideCopySelector();
      this.currentCopyItem = this.currentCViewArea;
      this.currentCopyItemState = this.currentCViewArea.getCopyState();
      this.checkCopyPasteState();
    }
  },
  
  copySelected: function D_copySelected() {
    if(this.currentCViewArea.selectedItem != null) {
      this.hideCopySelector();
      this.currentCopyItem = this.currentCViewArea.selectedItem;
      this.currentCopyItemState = NULL;
      this.checkCopyPasteState();
    }
  },
  
  onCopyBg: function D_onCopyBg(event) {
    var thisTime = new Date().getTime();
    if(this.copyDropDownTime != null && thisTime - this.copyDropDownTime < 500) {
      log("Aborting onCopyBg: thisTime=" + thisTime + " this.copyDropDownTime=" + this.copyDropDownTime);
       this.copyDropDownTime = null;
       return; //this was the mouse up event from when we bound it... we ignore it....
    }
    var element = Event.element(event);
    if(element != null && element.className == "disabled") return;
    
    //$("qty_selector_sprites").style.top = "-22px";
    this.hideCopySelector();
    
  },
  
  hideCopySelector: function D_hideCopySelector() {
    $("copy_dropdown_float").hide();
    this.copyDropDownActive = false;
    Event.stopObserving(document.body, "mouseup", this.onCopyBgEvent);
  },
  
  checkCopyPasteState: function D_checkCopyPasteState() {
    if(this.currentCViewArea.selectedItem == null) {
      $("copy_item_button").className = "disabled";  
    } else {
      $("copy_item_button").className = "";
    }   
    if(hashFirstElement(this.currentCViewArea.allItems) == null) {
      $("copy_area_button").className = "disabled";
      $("copy_button").className = "disabled";
    } else {
      $("copy_area_button").className = "";
      $("copy_button").className = "";
    }
    if(this.currentCopyItem != null) {
      $("paste_button").className = "";
    } else {
      $("paste_button").className = "disabled";
    }
  },
  
  paste: function D_paste() {
    log("D_paste");
    if(this.currentCopyItem == null) return;
    var results = this.currentCopyItem.copyTo(this.currentCViewArea, this.currentCopyItemState);
    if(results[0] != results[1]) {
      if(results[1] == 1) {
        alert(ml("Unable to paste item because target decoration area does not support the items decoration process")); 
      } else if(results[0] == 0) {
        alert(ml("Unable to paste any items because target decoration area does not support the items decoration process")); 
      } else {
        alert(ml("Not all items could be pasted because target decoration area does not support the items decoration process (%1s/%2s)", results));
      }
    }
  }
});
