var ProductType = Class.create({
  CLASSDEF: {
      name: 'ProductType'
  },
  
  initialize: function PT_initialize(id, options) {
    this.id = id;
    this.options = options;
    this.optionsById = new Hash();
    this.cats = [];
    this.catsById = new Hash();
    this.catsLoaded = false;
    this.name = options.name;
    this.ms = options.ms;
    
    //this.viewsAreDerived = options.vad; moved to product.hasDerivedViews
    this.noCategores = options.ddp;
    
    if(this.noCategores == true) { //no categories.....
      var notCat = new Category({id:-1,n:"No Category"}, this);
      this.cats.push(notCat);
      this.catsById[-1] = notCat;
      this.catsLoaded = true;
    }
    
    this.pricingType = options.pt;
    this.flags = options.flags;
    this.hasSizes = options.hs;
    
    
    this.fields = new MapList(this);
    this.fieldsByCode = {};
    this.fieldsByName = {};
    this.colorField = null;
    this.sizeField = null;
    this.customFields = new MapList(this);
    
    this.minQty = options.mq;
    this.bundleSize = options.bs;
    
    var fl = options.f;
    for(var i=0;i<fl.length;i++) {
      var f = new ProductTypeField(fl[i].id, fl[i], this);
      if(f.fieldType != FIELD_TYPE_PRODUCT_SIZE || this.hasSizes) {
        this.fields.add(f);
        if(f.code != null && f.code != '') {
          this.fieldsByCode[f.code] = f;
        }
        if(f.name != null && f.name != '') {
          this.fieldsByName[f.name] = f;
        }
        
        if(f.fieldType == FIELD_TYPE_PRODUCT_SIZE) {
          this.sizeField = f;
        } else if(f.fieldType == FIELD_TYPE_PRODUCT_COLOR) {
          this.colorField = f;
        } else {
          this.customFields.add(f);
        }
      }
    }
    this.currentCategory = null;
    this.currentSubCategory = null;
    this.boundElements = false;
    this.taxExempt = options.te;
    
    this.processes = new MapList(this);
  },
  
  addCategories: function PT_addCategories(cats) {
    //if(this.noCategores != true) {
      this.cats = [];
      this.catsById = new Hash();
      for(var i=0;i<cats.length;i++) {
        var cat = new Category(cats[i], this);
        this.cats.push(cat);
        this.catsById[cat.id] = cat;
      }
      this.catsLoaded = true;
    //}
  },
  
  addProcess: function PT_addProcess(options) {
    return this.processes.add(new ProductTypeProcess(this,options));
  },
  
  addProcessMix: function PT_addProcessMix(from, to) {
    var proc = this.processes.byId[from];
    if(proc != null) {
      proc.addMix(to);
    }
  },
  
  loadCategory:function(catId, products) {
    var cat = this.catsById[catId];
    if(cat!=null) {
      cat.load(products);
    }
    return cat;
  },
  
  getColorPanel: function PT_getColorPanel() {
    if(this.colorPanel!=null) {
      return this.colorPanel;
    }
    if(this.noColorPanel) {
      return null;
    }
    this.colorPanel = $("pt_col_" + this.id);
	
    if(this.colorPanel==null) {
      this.noColorPanel = true;
    } else {
      this.colorPanel.className="color_panel";
    }
    return this.colorPanel;
  },
  
  buildColorPanel: function PT_buildColorPanel(cProduct) {
    var cp = this.getColorPanel();
    
    var html = '';
    
    if(cp != null) {
      var count = 0;
      var colors = cProduct.getAvailableColorList();
      
      for(var i = 0; i < colors.length;i++) {
        var color = colors[i];
        //log(color);
        var int_title="";
        for(var k=0; k < color.colors.length; k++) {
          int_title+= color.colors[k][1] + ' ';
        }
        var cellHtml = '<li><a href="#" class="color_panel_cell" title="'+int_title+'" id="cpc_' + color.id + '" onmousemove="d.colorMouseMove(this, ' + color.id + ');" onmouseout="d.colorMouseOut(this, ' + color.id + ');">';
        var h = parseInt(20 / color.colors.length, 10);
        for(var j=0; j < color.colors.length;j++) {
          cellHtml += '<span style="background-color: ' + color.colors[j][0] + '; height: '+h+'px;">&nbsp;</span>';
        }
        cellHtml += "<b>&nbsp;</b></a></li>";
        html += cellHtml;
        count += 1;
      }
     // html += "<!--</ul>-->";
      
      log("setting color panel");
      //log(html);
      Element.update(cp, html);
      log("setting color panel- DONE");
      
      //choose selected colorcolor_cell
      var f = this.colorField;
      if(f != null) {
        var c = null;
        var selectedColorId = cProduct.getSelectedColorId();
        var cpc = $("cpc_" + selectedColorId);
        if(cpc==null) {
          log("Unable to get selected color cell for color " + selectedColorId);
        } else {
          cpc.className += " selected";
          this.selectedColorCell = cpc;
        }
      }
      //bind the color cells
      for(var i = 0; i < colors.length;i++) {
        var color = colors[i];
        var cpc = $("cpc_" + color.id);
        this.bindColorCell(cpc, color);
      }
    }
  },
  
  bindColorCell: function PT_bindColorCell(el, color) {
    var self = this;
    el.onclick = function() {
      if(self.selectedColorCell!=null) {
        self.selectedColorCell.className = self.selectedColorCell.className.replace(" selected", "");
      }
      d.track("change-product-color");
      self.selectedColorCell = el;
      self.selectedColorCell.className = self.selectedColorCell.className+ " selected";
      d.currentCProduct.selectColor(color);
      //self.updateProductViews(true, true);
      d.itemChanged();
      return false;
    };
  },
  
 
  
  //select this product type
  //cProduct: the current configured product..  if different type than this then set product to first product of this type
  //doUpdate: update the designer view
  //doSelect: select the first item 
  selectConfiguredProduct: function PT_selectConfiguredProduct(cProduct, doUpdate, doSelect) {
    log("Selecting Configured Product", true);
    d.deSelectCurrentItem();
    var rebuildImages = false;
    if(cProduct.product.type != this) {
      //swapped product types.... we dont want to select 'product', we just pass it to flag product type change
      log("swapping products type..");
      var cat = this.getFirstLoadedCat();
      /*if(cat == null) {
        log("product type does not have a loaded cat... getting now");
        var self = this;
        this.cats[0].getProducts(function() {
          self.selectConfiguredProduct(cProduct, doUpdate, doSelect);
          } , "m_apparel_pane");
        return;
      }*/
      var new_prod = d.getProduct(cat.products[0].id, null, null);
      if(new_prod == null) {
        log("product " + cat.products[0].id + " not cached.. getting now..");
        var self = this;
        d.getProduct(cat.products[0].id, function() {
          self.selectConfiguredProduct(cProduct, doUpdate, doSelect);
        } , "m_apparel_pane");
        return;
      }
      var moveResult = cProduct.productChangeWillMatch(new_prod);
      if(moveResult != 0) {
        var warning = moveResult==2 ? ml("Some of the artwork you have done cannot be used on the product you have selected. Are you sure you want to change the product?") : ml("None of the artwork you have done can be used on the product you have selected. Are you sure you want to change the product?") ;
        
        if(!confirm(warning)) {
          this.showProductAsSelected( cProduct.product);
          return;
        }
      }
      d.deSelectCurrentItem();
      cProduct.setProduct(new_prod);
      rebuildImages = true;
      cProduct.price = null;
      
    }
    
    var productCaption = $("left_title");
    if(productCaption!= null) {
      if (cProduct.usingCustomProduct()) {
        productCaption.innerHTML = cProduct.customProduct.name;
      } else {
        productCaption.innerHTML = cProduct.product.name;
      }
    }
    
    /*
    DNC-4007 - we now want this back all the time...
    var previewEl = $("show_preview");
    if(previewEl != null) {
      if(cProduct.product.hasDerivedViews) {
        previewEl.show();
      } else {
        previewEl.hide();
      }
    }
    */
    
    cProduct.updateViewListHtml();
    this.buildColorPanel(cProduct);
    log("this.buildColorPanel");
    this.setFields(cProduct);
    log("this.setFields");
    //select the category etc...
    var cat = this.catsById[cProduct.product.categoryId];
    if((cat != this.currentCategory)&&(cat!=null)&&(this.currentCategory!=null)&&(d.mode != DESIGNER_MODE_VIEW_CUSTOM_PRODUCT)) {
      this.markCategorySelected(0); //move to 'all'
      this.selectCategory(0, cProduct.product.id); //render 'all' listing
      this.selectProductInListing(cProduct.product.id); //visually mark as selected
      if(doUpdate) {
        d.selectCurrentView(cProduct.getFirstSelectedViewId(), null);
        if(doSelect) {
          if(!d.currentCViewArea.findAndSelectItem()) {
            d.selectTab('m','customize');
          }
        }
        this.showEditing();
      }
      this.doShow();
    } else if(doUpdate) {
      this.selectProductInListing(cProduct.product.id); //visually mark as selected
      d.selectCurrentView(cProduct.getFirstSelectedViewId(), null);
      if(doSelect) {
        if(!d.currentCViewArea.findAndSelectItem()) {
          d.selectTab('m','customize');
        }
      }
      this.showEditing();
      this.doShow();
    } else {
      this.doShow();
    }
    if(cProduct.product.usesMinQty()) {
      $("c_bun_info").show();
      $("c_min_qty").innerHTML=cProduct.product.minQty;
      $("c_bun").innerHTML=cProduct.product.bundleSize;
      $("qty_container").className = "qty_dropdown";
    } else {
      $("c_bun_info").hide();
      $("qty_container").className = "";
    }
    cProduct.qty = cProduct.checkQty(cProduct.qty, true, true);
    $("qty").value = cProduct.qty; //the qty can change when multiple sizes option is selected and some sized are not available in new product
    this.updatePrice();
    
    
    
  },
  
  setFields: function PTF_setFields(cProduct) {
    for(var i=0;i< this.fields.list.length;i++) {
      if(this.fields.list[i].fieldType != FIELD_TYPE_PRODUCT_COLOR) {
        this.fields.list[i].setField(cProduct);
        //this.setField(this.fields.list[i], cProduct);
      }
    }
  },
  
  getFirstLoadedCat: function PT_getFirstLoadedCat() {
    for(var i=0; i < this.cats.length; i++) {
      if(this.cats[i].products != null) {
        return this.cats[i];
      }
    }
    return null;
  },
  
  //the user has selected a different product from the product list
  changeSelectedProduct: function PT_changeSelectedProduct(productId) {
    d.deSelectCurrentItem();
    var p = d.currentCProduct;
    var self = this;
    d.track("change-selected-product");
    d.getProduct(productId, function(product) {
        
      
      log("changeSelectedProduct callback");
      var moveResult = p.productChangeWillMatch(product);
      if(moveResult != 0) {
        var warning = moveResult==2 ? ml("Some of the artwork you have done cannot be used on the product you have selected. Are you sure you want to change the product?") : ml("None of the artwork you have done can be used on the product you have selected. Are you sure you want to change the product?") ;
        
        if(!confirm(warning)) {
          //cat.selectProduct(cProduct.product.id);
          self.showProductAsSelected( p.product);
          return;
        }
      }
      d.deSelectCurrentItem();
      self.showProductAsSelected(product);
      p.setProduct(product);
      log("p.setProduct(product);");
      self.selectConfiguredProduct(p,false, false);
      p.afterProductChanged();
      log("self.selectConfiguredProduct(p,false, false);");
      self.updateProductDetails(true);
      
      d.selectCurrentView(p.getFirstSelectedViewId(), null);
      //self.updateProductViews(true);
      log("changeSelectedProduct callback DONE");
    }, $("pt_info_" + this.id));
  },
  
  //show a product as selected on product selector.. assumes the current product type/cat is the same...if not do nothing
  showProductAsSelected: function PT_showProductAsSelected(product) {
    if(d.mode == DESIGNER_MODE_VIEW_CUSTOM_PRODUCT) return; //viewing custom product...
    if(this.id != product.type.id) {
      return;
    }
    this.selectProductInListing(product.id);
  },
  
  updateProductDetails: function PT_updateProductDetails() {
    if(d.mode==DESIGNER_MODE_VIEW_CUSTOM_PRODUCT) {
      return;
    }
    var p = d.currentCProduct.product;
    var img = $("pt_i_" + this.id);
    if(img != null) setImageUrl(img, img, p.getDisplayImageURL(), null);
    //$("pt_i_" + this.id).src = p.getViewURL(p.product.defaultView.id, 2);
    var el = $("pt_c_" + this.id);
    if(el != null) el.innerHTML = p.name;
    var el = $("pt_d_" + this.id);
    if(el != null) el.innerHTML = p.description;
  },
  
  
  deselect: function PT_deselect() {
    if (this.container != null) this.container.hide();
    //this.views.style.display = "none"; 
    if (this.dataContainer != null) this.dataContainer.hide();
    if (this.fieldsContainer != null) this.fieldsContainer.hide();
    if (this.catSelectorContainer != null) this.catSelectorContainer.hide();
    var cp = this.getColorPanel();
    if(cp != null) cp.hide();
  },
  
  //show the product type information, calling the server if we dont have it locally yet...
  select: function PT_select(callback, selectedCategoryId, productId) {
    if(this.boundElements) {
      this.container.show();
      //this.views.style.display = ""; 
      this.dataContainer.show(); 
      if((d.mode == DESIGNER_MODE_CONFIGURE)&&(!d.configuringNewProduct)) {
        $("m_apparel").hide();
      } else {
        if(d.mode != DESIGNER_MODE_CONFIGURE) {
          this.fieldsContainer.show();
        } else {
          this.fieldsContainer.hide();
        }
        if (this.catSelectorContainer != null) this.catSelectorContainer.show();
        if(this.noCategores) {
          $("product_category_container").hide();
        } else {
          $("product_category_container").show();
        }
      }
      var cp = this.getColorPanel();
      if(cp != null) cp.show();
      callback();
      return true;
    } else {
      var self = this;
      var aKey = asyncStart("designer_container");
      var t2 = new Ajax.Request(d.ajaxUrl(d.pathPrefix + "/designer/get_product_type_configuration_panel?id=" + this.id + "&pid=" + productId + "&cats_loaded=" + this.catsLoaded), {asynchronous:true, evalScripts:true, 
        onComplete: function PT_onComplete() { 
          asyncFinish(aKey); 
          self.bindElements();
          self.selectCategory(0);
          callback();
        }
      });
    }
  },
  
  bindElements: function PT_bindElements() {
    this.boundElements = true;
    var self = this;
    this.container = $("pt_" + this.id);
    //this.views = $("product_views_" + this.id);
    this.dataContainer = $("product_type_data_" + this.id);
    this.fieldsContainer = $("product_type_cf_" + this.id);
    this.catSelectorContainer = $("category_selector_" + this.id);
    if(d.mode != DESIGNER_MODE_CONFIGURE) {
      this.fieldsContainer.show();
    } else {
      this.fieldsContainer.hide();
    }
   
    var ddel = $("ddpc_" + this.id);
    if(ddel != null) {
      this.bindCatSelector($("ddpc_" + this.id));
    }
    if((d.mode == DESIGNER_MODE_CONFIGURE)&&(!d.configuringNewProduct)) {
      $("m_apparel").hide();
    } else {
      if (this.catSelectorContainer != null) this.catSelectorContainer.show();
      if(this.noCategores) {
        $("product_category_container").hide();
      } else {
        $("product_category_container").show();
      }
    }
  },

  bindCatSelector: function PT_bindCatSelector(el) {
    this.catSelectorEl = el;
    var self = this;
    log("bindCatSelector");
    log(el);
    el.onchange = function() {
      log("Cat Changed:" + el.value);
      var catId = el.value;
      self.selectCategory(parseInt(catId, 10));
      self.selectProductInListing(d.currentCProduct.product.id);
    };
  },
  
  selectCategory: function(categoryId) {
    if(this.noCategores != true) {
      if(categoryId == 0) {
        var html = '';
        for(var i=0; i < this.cats.length; i++) {
          var cat = this.cats[i];
          var cHtml = '<h3>' + cat.name + '</h3><ul>';
          cHtml += cat.generateHtml();
          cHtml += '</ul>';
          html += cHtml;
        }
        html += '';
        Element.update("product_list_" + this.id, html);
        for(var i=0; i < this.cats.length; i++) {
          var cat = this.cats[i];
          cat.bindElements();
        }
      } else {
        var cat = this.catsById[categoryId];
        cat.displayProducts();
      }
    } else {
      var cat = this.catsById[-1];
      cat.displayProducts();
    }
  },
  
  markCategorySelected: function PT_markCategorySelected(categoryId) {
    if(this.catSelectorEl != null) {
      this.catSelectorEl.value = categoryId;
    } 
  },
  
  selectProductInListing: function(productId) {
    if(this.currentCategory!=null) {
      this.currentCategory.selectProduct(productId);
    } else { //all selected..
      for(var i=0; i < this.cats.length; i++) {
        this.cats[i].selectProduct(productId);
      }                                     
    }
  },
  
  //depricated
  scrollCat: function PT_scrollCat(amount) {
    if(this.currentCategory!=null) {
      this.currentCategory.scrollCat(amount);
    }
  },
  
  updatePrice: function PT_updatePrice() {
    var up = d.currentCProduct.getUnitPrice();
    var price = d.currentCProduct.getPrice();
    var discount = d.currentCProduct.discount;
    var qty = d.currentCProduct.qty;
    //$("qty").value = qty; (this was stopping user from backspacing the qty before changing it)
    $('price').innerHTML = d.formatPrice(price, "price_currency_code");
    var disc = $("discount_container");
    if(disc != null) {
      if(discount > 0) {
        disc.style.display="";
         $("discount").innerHTML = d.formatPrice(discount,"discount_currency_code");
      } else {
        disc.style.display="none";
      }
    }
    if(d.pricesToUpdate){
      this.updatePrintingProcessPrices();
    }
  },
  
  updatePrintingProcessPrices: function PT_updatePrintingProcessPrices(){
    var originalPP = d.currentCProduct.defaultProcessId ;
    var originalUserPP = d.userSelectedProcessId;
    d.userSelectedProcessId = null;
    var pps = d.pricesToUpdate,
      length = pps.length,
      i = length ;
    while (--i >= 0) {
      var pp = pps[i],
        el = $(pp.ele) ;
      d.currentCProduct.defaultProcessId = pp.id ;
      d.currentCProduct.getUnitPrice() ;
      el.innerHTML = d.formatPrice(d.currentCProduct.getPrice(), "price_currency_code") ;
    }
    d.currentCProduct.defaultProcessId = originalPP ;
    d.userSelectedProcessId = originalUserPP;
  },
  
  showEditing: function PT_showEditing(fromSave) {
    if(d.mode==DESIGNER_MODE_VIEW_CUSTOM_PRODUCT) {
      return;
    }
    if(fromSave) {
      $("add_cart_container").style.display = "none";
      $("update_cart_container").style.display = "none";
    } else {
      log("showEditing", true);
      if(d.currentCProduct.addedToCart) {
        $("add_cart_container").style.display = "none";
        $("update_cart_container").style.display = "";
      } else {
        $("add_cart_container").style.display = "";
        $("update_cart_container").style.display = "none";
      }
      $("qty").value = d.currentCProduct.qty;
      $("qty").disabled =(d.currentCProduct.multiOptionField() != null || d.defaultQtyDisabled);
    }
  },
  
  itemChanged: function PT_itemChanged() {
    $("qty").disabled = (d.currentCProduct.multiOptionField() != null || d.defaultQtyDisabled);
    if(d.mode==DESIGNER_MODE_VIEW_CUSTOM_PRODUCT) {
      return;
    }
    //log("item changed!", true);
    if(d.currentCProduct.addedToCart) {
      $("update_cart_container").style.display = "";
      //$("cancel_button").style.display = "";
    } else {
      $("add_cart_container").style.display = "";
      
    }
  },
  
  itemSaved: function PT_itemSaved() {
    if(d.mode==DESIGNER_MODE_VIEW_CUSTOM_PRODUCT) {
      return;
    }
    $("update_cart_container").style.display = "none";
    //$("cancel_button").style.display = "none";
    
  },
   //called to make sure any state of the current product is displayed in the designer
  doShow: function PT_doShow() {
    $("qty").disabled = (d.currentCProduct.multiOptionField() != null || d.defaultQtyDisabled);
  },
  
  canDecorate: function PT_canDecorate(process) {
    return (this.processes.byId[process.id] != null);
  },
  
  //get the disabled message.. for product type it would be 'You cannot add %1s to a %2s'
  getDecProcDisabledMessage: function PT_getDecProcDisabledMessage(process) {
    return "You cannot add " + process.name + " to a " + this.name;
  }
});

var ProductTypeField = Class.create({
  CLASSDEF: {
      name: 'ProductTypeField'
  },
  
  initialize: function PTF_initialize(id, options, productType) {
    this.id = id;
    this.name = options.n;
    this.code = options.c;
    this.fieldType = options.ft;
    this.productType = productType;
    
    
    
    this.description = options.d;
		this.pos = options.p;
		
    this.typeOptions = FIELD_TYPES_OPTIONS[this.fieldType];
		this.pricingType = options.pt;
		this.priceModifierType = options.pm;
    this.priceModifier = options.pta;
    
    this.percentOf = null;
    if(options.pco != null) {
      this.percentOf = options.pco;
    }
    this.defaultOn = options.don;

    this.isRequired = options.r;
    this.hasSubOptions = options.sub;
    this.customOptions = (options.co == null) ? {} : options.co;
    
    this.hasMulti = options.multi;

        
    if(this.hasMulti) {
      this.multiOptions = {};
      this.multiRow = $("multi_" + this.id);
    }
    
    this.options = new MapList();
    var lo = options.o;
    for(var i=0;i<lo.length;i++) {
      var o = new ProductTypeOption(lo[i].id, lo[i], this);
      this.options.add(o);
  
      this.productType.optionsById[o.id] = o;
      
      if((this.hasMulti) && (!o.isMulti)) {
        var optQty = $("mq_" + o.id);
        var optTd = $("m_" + o.id);
        this.multiOptions[o.id] = {td: optTd, q: optQty};
      } else if(o.isMulti) {
        this.multiOption = o;
      }
      
    }
  },
  
  //because the mutirow may not exist when the init contsructor is called be need late binding
  
  toggleMultiContainer: function PTF_toggleMultiContainer(show) {
    var el = $("multi_container_" + this.id);
    if(el != null) {
      if(show) {
        el.show();
      } else {
        el.hide();
      }
    }
    if(d.currentLayoutManager != null) {
      d.currentLayoutManager.recalibrate();
    }
  },
  
  //show the tr with the multiple qty options
  showMultiQtyOptions: function PTF_showMultiQtyOptions(cProduct) {
    this.toggleMultiContainer(true);
  },
  
  hideMultiQtyOptions: function PTF_hideMultiQtyOptions(cProduct) {
    this.toggleMultiContainer(false);
  },
  
  //called when changing/loading configured product: render/insert the html for this field....
  setField: function PTF_setField(cProduct) {
    if(this.fieldContainer == null) {
      this.fieldContainer = $("pt_fc_" + this.id);
      this.fieldOptionsContainer = $("pt_foc_" + this.id);
      if(this.fieldType != FIELD_TYPE_PRODUCT_SIZE) {
        var lblEl = $("cf_lbl_" + this.id);
        var toolEl = $("cf_tip_" + this.id);
        if((lblEl!=null)&&(toolEl!=null)) {
          new Tooltip(lblEl, toolEl);
        }
      }
    }
    var productField = cProduct.product.fields.byId[this.id];
    if((productField == null)||(!productField.valid)||(!productField.used)) { //this product does not use the field...
      if (this.fieldContainer != null) this.fieldContainer.hide(); 
      log("Hiding field " + this.name + ": productField follows:");
      log(productField);
    } else {
      var cField = cProduct.cFields[this.id];
      if (this.fieldOptionsContainer != null) this.fieldOptionsContainer.update(this.renderHtml(cProduct, productField, cField));
      if(d.mode != DESIGNER_MODE_CONFIGURE) {
        if (this.fieldContainer != null) this.fieldContainer.show();
      } else {
        if (this.fieldContainer != null) this.fieldContainer.hide();
      }
    }
  },
  
  customOption: function PTF_customOption(name, defaultValue) {
    var opt = this.customOptions[name];
    if(opt==null) opt = defaultValue;
    return opt;
  },
  
  renderHtml: function PTF_renderHtml(cProduct, pField, cField) {
    
    if(this.typeOptions.list) {
      return this.renderListHtml(cProduct, pField, cField);
    } else if(this.fieldType == FIELD_TYPE_TEXT_BOX) {
      var disCode = (d.mode == DESIGNER_MODE_AMEND && this.priceModifierType != PRICE_MODIFY_NONE && cField.getValue(null) == null) ? ' disabled="true"' : '';
      return '<input type="text" size="' + this.customOption("length", 30) + '" value="' + cField.getValue('') + '"' + cField.iId('value', true) + ' onblur="' + cField.objectRef() + '.setValue(this.value);"' + disCode + '/>';
    } else if(this.fieldType == FIELD_TYPE_TEXT_AREA) {
      var disCode = (d.mode == DESIGNER_MODE_AMEND && this.priceModifierType != PRICE_MODIFY_NONE && cField.getValue(null) == null) ? ' disabled="true"' : '';
      return '<textarea ' + disCode + ' rows="' + this.customOption("rows", 5) + '" cols="' + this.customOption("cols", 30) + '"' + cField.iId('value', true) + ' onblur="' + cField.objectRef() + '.setValue(this.value);">' + cField.getValue('') + '</textarea>';
    } else if(this.fieldType == FIELD_TYPE_FILE) {
      var disCode = (d.mode == DESIGNER_MODE_AMEND && this.priceModifierType != PRICE_MODIFY_NONE && cField.getValue(null) == null) ? ' disabled="true"' : '';
      var existing = "";
      if(cField.getValue(null) != null) {
        var fileData = cField.getValue(null);
        existing = ' <a href="' + fileData.url + '" target="_BLANK">' + fileData.name + '</a> (' + fileData.file_size + ') <a href="#" onclick="' + cField.objectRef() + '.removeFile(); return false;" class="file_remove">' + ml("Remove") + '</a>';
      }
      return '<form id="field_upload_form' + this.id + '" method="post" enctype="multipart/form-data" action="/designer/upload_file?field_id=' + this.id + '&c_product_id=' + cProduct.id + '&s_product_id=' + cProduct.product.id + '" target="UploadTarget">' +
        '<input size="5" name="field_file" type="file" ' + cField.iId('value', true) + ' onchange="' + cField.objectRef() + '.setValue(this.value);" value="' + cField.getValue('') + '"' + disCode + '/>' + existing +
       '</form>';
    } else if(this.fieldType == FIELD_TYPE_IMAGE) {
      var disCode = (d.mode == DESIGNER_MODE_AMEND && this.priceModifierType != PRICE_MODIFY_NONE && cField.getValue(null) == null) ? ' disabled="true"' : '';
      var existing = "";
      if(cField.getValue(null) != null) {
        var fileData = cField.getValue(null);
        existing = ' <img src="' + fileData.url_thumb + '" >' + ' (' + fileData.width + "x" + fileData.height + " " + fileData.file_size + ') <a href="#" onclick="' + cField.objectRef() + '.removeFile(); return false;" class="file_remove">' + ml("Remove") + '</a>';
      }
      return '<form id="field_upload_form' + this.id + '" method="post" enctype="multipart/form-data" action="/designer/upload_file?field_id=' + this.id + '&c_product_id=' + cProduct.id + '" target="UploadTarget">' +
        '<input size="5" name="field_file" type="file" ' + cField.iId('value', true) + ' onchange="' + cField.objectRef() + '.setValue(this.value);" value="' + cField.getValue('') + '"' + disCode + '/>' + existing +
       '</form>';
    } else if((this.fieldType == FIELD_TYPE_DATE)||(this.fieldType == FIELD_TYPE_DATE_TIME)) {
      var disabled = (d.mode == DESIGNER_MODE_AMEND && this.priceModifierType != PRICE_MODIFY_NONE && cField.getValue(null) == null);
      if(disabled) {
        return "Cannot Set Date When Ammending Order";
      }
      var format = parseInt(this.customOption("date_format", '0'), 10);
      var type = parseInt(this.customOption("date_input_type", '0'), 10);
      var includeTime = (this.fieldType == FIELD_TYPE_DATE_TIME);
      var timeFormat = includeTime? parseInt(this.customOption("time_format", '0'), 10) : -1;
      var defValue = parseInt(this.customOption("default_value", '0'));
      var curDate = null;
      if (defValue != null && (defValue > 0 || defValue <= 0)) {
        curDate = new Date();
        if (includeTime) {
          curDate.setTime(curDate.getTime() + defValue * 3600000);
        } else {
          curDate.setTime(curDate.getTime() + defValue * 3600000 * 24);
        }
      }
      
      if(type == 0) { //date picker...
        var currentDate = this.formatDate(format, curDate, includeTime, "Select Date");
        var dataDate = (curDate == null) ? "" :  curDate.toString();
        
        return '<a href="#" onclick="' + cField.objectRef() + '.selectDate(' + includeTime + '); return false;" class="field_date_picker"><input type="hidden" id="field_date_value_' + this.id + '" value="' + dataDate + '"/><span id="field_date_' + this.id + '">' + currentDate + '</span></a> <a href="#" onclick="' + cField.objectRef() + '.selectDate(' + includeTime + '); return false;" class="field_date_picker"><img src="/images/calendar_date_select/calendar.gif" border="0"/></a>'
      } else { //input fields
        var str = this.renderDateInputs(format, curDate, cField.objectRef(), cField);
        if(includeTime) {
          str += this.renderTimeInputs(timeFormat, curDate, cField.objectRef(), cField);
        }
        return str;
      }
    } else if(this.fieldType == FIELD_TYPE_TIME) {
      var disabled = (d.mode == DESIGNER_MODE_AMEND && this.priceModifierType != PRICE_MODIFY_NONE && cField.getValue(null) == null);
      if(disabled) {
        return "Cannot Set Date When Ammending Order";
      }
      var timeFormat = parseInt(this.customOption("time_format", '0'), 10);
      var defValue = parseInt(this.customOption("default_value", '0'));
      var curDate = null;
      if (defValue != null && (defValue > 0 || defValue <= 0)) {
        curDate = new Date();
        curDate.setTime(curDate.getTime() + defValue * 3600000);
      }
      return this.renderTimeInputs(timeFormat, curDate, cField.objectRef(), cField);
    }
  },
  
  renderDateInputs: function PTF_renderDateDropDowns(format, date, objectRef, cField) {
    var dateFieldOrder = {
      0: ["m","/", "d", "/", "y"],
      1: ["d","/", "m", "/", "y"],
      2: ["sm"," ", "d", ", ", "y"],
      3: ["lm"," ", "d", ", ", "y"]
    };
    var fields = dateFieldOrder[format];
    var str = "";
    
    for(var i=0; i < fields.length; i++) {
      var fieldCode = fields[i];
      switch(fieldCode) {
      case "m": 
        var selVal = (date == null)? -1 : date.getMonth();
        str += '<select ' + cField.iId("date_1", true) + ' onchange="' + objectRef + '.setValue(this.value, 1);">' + selectOptionHtml([["",-1],["01-Jan",0],["02-Feb",1],["03-Mar",2],["04-Apr",3],["05-May",4],["06-Jun",5],["07-Jul",6],["08-Aug",7],["09-Sep",8],["10-Oct",9],["11-Nov",10],["12-Dec",11]], selVal) + '</select>'; 
        break;
      case "d": 
        var selVal = (date == null)? "" : date.getDate();
        str += '<input ' + cField.iId("date_0", true) + ' type="text" size="2" onblur="' + objectRef + '.setValue(this.value, 0);" value="' + selVal + '"/>'; 
        break;
      case "y": 
        var selVal = (date == null)? -1 : date.getFullYear();
        var y = new Date().getFullYear();
        var years = $R(y - 10, y + 10);
        str += '<select ' + cField.iId("date_2", true) + ' onchange="' + objectRef + '.setValue(this.value, 2);">' + selectOptionHtml([""].concat(years.toArray()), selVal) + '</select>'; 
        break;
      case "sm": 
        var selVal = (date == null)? -1 : date.getMonth();
        str += '<select ' + cField.iId("date_1", true) + ' onchange="' + objectRef + '.setValue(this.value, 1);">' + selectOptionHtml([["",-1],["Jan",0],["Feb",1],["Mar",2],["Apr",3],["May",4],["Jun",5],["Jul",6],["Aug",7],["Sep",8],["Oct",9],["Nov",10],["Dec",11]], selVal) + '</select>'; 
        break;
      case "lm": 
        var selVal = (date == null)? -1 : date.getMonth();
        str += '<select ' + cField.iId("date_1", true) + ' onchange="' + objectRef + '.setValue(this.value, 1);">' + selectOptionHtml([["",-1],["January",0],["February",1],["March",2],["April",3],["May",4],["June",5],["July",6],["August",7],["September",8],["October",9],["November",10],["December",11]], selVal) + '</select>'; 
        break;
      default:
        str += fieldCode;
      }
    }
    return str;
  },
  
  renderTimeInputs: function PTF_renderTimeInputs(format, date, objectRef, cField) {
    var str = "";
    var selVal = null;
    if(format == 0) { //ampm
      selVal = (date == null)? "" : date.getAMPMHour();
      str += '<input ' + cField.iId("date_3", true) + ' type="text" size="2" onblur="' + objectRef + '.setValue(this.value, 3);" value="' + selVal + '"/>';
    } else {
      selVal = (date == null)? "" : date.getHour();
      str += '<input ' + cField.iId("date_6", true) + ' type="text" size="2" onblur="' + objectRef + '.setValue(this.value, 6);" value="' + selVal + '"/>';
    }
    selVal = (date == null)? "" : date.getMinutes();
    str += '<input ' + cField.iId("date_4", true) + ' type="text" size="2" onblur="' + objectRef + '.setValue(this.value, 4);" value="' + selVal + '"/>';
    if(format == 0) { //ampm
      selVal = (date==null)? '' : date.getAMPM();
      str += '<select ' + cField.iId("date_5", true) + ' onchange="' + objectRef + '.setValue(this.value, 5);">' + selectOptionHtml(["AM","PM"], selVal) + '</select>'; 
    }
    return str;
  },
  
  formatDate: function PTF_formatDate(format, date, includeTime, defaultValue) {
    if(date == null) {
      return defaultValue;
    }
    return date.toFormat(format, includeTime);
  },
  
  updateDate: function(cField) {
    var format = parseInt(this.customOption("date_format", '0'), 10);
    if(this.fieldType == FIELD_TYPE_DATE) {
      var currentDate = this.formatDate(format, cField.fieldValue, false, "Select Date");
      $('field_date_' + this.id).update(currentDate);
    } else {
      var currentDate = this.formatDate(format, cField.fieldValue, true, "Select Date");
      $('field_date_' + this.id).update(currentDate);
    }
  },
  
  renderListHtml: function PTF_renderListHtml(cProduct, pField, cField) {
    var sizeColorCombinations = null;
    if(this.fieldType == FIELD_TYPE_PRODUCT_SIZE && cProduct.product.limitSizeColors) {
      sizeColorCombinations = cProduct.product.sizeColorCombinations;
    }
    var html = '';
    if((this.fieldType == FIELD_TYPE_PRODUCT_SIZE && !this.productType.ms) || (this.fieldType == FIELD_TYPE_PRODUCT_SIZE && (cProduct.usingTeamnames || cProduct.product.usesMinQty())) || this.fieldType ==FIELD_TYPE_LIST_MULTISELECT_QTY || this.fieldType ==FIELD_TYPE_LIST_MULTISELECT || this.fieldType == FIELD_TYPE_LIST_DROPDOWN) {
      html = this.renderSelect(cProduct, pField, cField, sizeColorCombinations);
    }
    if(this.fieldType == FIELD_TYPE_LIST_CHECKBOX || this.fieldType ==FIELD_TYPE_LIST_RADIO) {
      html = this.renderCheckRadio(cProduct, pField, cField);
    }
    if(this.fieldType == FIELD_TYPE_PRODUCT_SIZE || this.fieldType ==FIELD_TYPE_LIST_MULTISELECT_QTY) {
      log("renderMultiQty");
      html += this.renderMultiQty(cProduct, pField, cField, sizeColorCombinations);
    }
    
    return html;
  },
  
  checkSizeColorCombination: function PTF_checkSizeColorCombination(sizeColorCombinations, selectedColor, ptOpt) {
    if((sizeColorCombinations != null)&&(selectedColor != null)&&(!ptOpt.isMulti)) {
      var filter = sizeColorCombinations[ptOpt.id];
      if(filter != null) {
        if(filter[selectedColor.productChosenOptionId] != true) {
          log("Filtering out " + ptOpt.name);
          return false;
        }
      } else {
        log("product has no available colors for size " + ptOpt.name);
        return false;
      }
    }
    return true;
  },
  
  renderSelect: function PTF_renderSelect(cProduct, pField, cField, sizeColorCombinations) {
    if(this.fieldType == FIELD_TYPE_PRODUCT_SIZE && cProduct.usingTeamnames) {
      return '<a href="#" onclick="d.currentCProduct.getTeamNames().editTeamNames(); return false;">Manage Teamnames</a>';
    }
    log("renderSelect");
    var multiMode = false;
    var size = 0;
    var multi = false;
    
    if(this.fieldType == FIELD_TYPE_PRODUCT_SIZE || this.fieldType ==FIELD_TYPE_LIST_MULTISELECT_QTY || this.fieldType ==FIELD_TYPE_LIST_DROPDOWN) { //"multi select" may be chosen
      if(cField.multiSelect) {
        multiMode = true;
      }
    } else {
      size = 5;
      multi = true;
    }
    
    var opts = this.getOptionList(cProduct, pField, cField, sizeColorCombinations, true);
    
    var selOpt = cField.getMainOption(true);
      
    var optionHtml = selectOptionHtml(opts, selOpt.getId());
    
       
       
       
    var extraSelOpts = "";
    if(size > 1) {
      extraSelOpts += ' size="' + size + '"';
    }
    if(multi) {
      extraSelOpts += ' multiple="multiple"';
    }
    var selCode = multi ? 'null' : 'this.value';
    var disCode = (d.mode == DESIGNER_MODE_AMEND && this.priceModifierType != PRICE_MODIFY_NONE) ? ' disabled="true"' : '';
    return '<select ' + cField.iId('value', true) + ' onchange="' + cField.objectRef() + '.setValue(' + selCode + ');" ' +  extraSelOpts + disCode + '>' + optionHtml + '</select>';
  },
  
  getOptionList: function PTF_getOptionList(cProduct, pField, cField, sizeColorCombinations, includeMulti) {
    var selectedColor = cProduct.getSelectedColor();
    if(selectedColor == null) log("Unable to filter out sizes as selected color is null");
    var opts = [];
    for(var i=0; i < this.options.list.length; i++) {
      var ptOpt = this.options.list[i];
      var pOpt = pField.options.byId[ptOpt.id];
      if(pOpt != null) {
        if(!this.checkSizeColorCombination(sizeColorCombinations, selectedColor, ptOpt)) {
          delete cField.options[ptOpt.id]; //just make sure its not selected..
          continue;
        }
        if(pOpt.subs != null) {
          var subOpts = [];
          for(var j=0; j < ptOpt.subs.list.length; j++) {
            var ptSubOpt = ptOpt.subs.list[j];
            var pSubOpt = pOpt.getSubOption(ptSubOpt.id);
            if(pSubOpt != null) {
              subOpts.push([ptSubOpt.name,ptOpt.id + '-' + ptSubOpt.id]);
            }
          }
          if(subOpts.length > 0) {
            opts.push({ c:ptOpt.name, v:subOpts});
          }
        } else if(!ptOpt.isMulti || includeMulti) {
          
          opts.push([ptOpt.name,pOpt.id]);
        }
      }
    }
    return opts;
  },
  
  renderMultiQty: function PTF_renderMultiQty(cProduct, pField, cField, sizeColorCombinations, idPrefix, renderEvents, forceVisible) {
    log("renderMultiQty");
    if(idPrefix == null) idPrefix = "";
    if(renderEvents==null) renderEvents = true;
    var dis = (cField.multiSelect || forceVisible) ? '' : ' style="display:none;"' ;
    var en = ((d.mode == DESIGNER_MODE_AMEND && this.priceModifierType != PRICE_MODIFY_NONE)||(this.fieldType == FIELD_TYPE_PRODUCT_SIZE && cProduct.usingTeamnames && renderEvents)) ? ' disabled="true"' : '';
    var selectedColor = cProduct.getSelectedColor();
    if(selectedColor == null) log("Unable to filter out sizes as selected color is null");
    var opts = [];
    for(var i=0; i < this.options.list.length; i++) {
      var ptOpt = this.options.list[i];
      if(ptOpt.isMulti) continue;
      var pOpt = pField.options.byId[ptOpt.id];
      if(pOpt != null) {
        if(!this.checkSizeColorCombination(sizeColorCombinations, selectedColor, ptOpt)) {
          delete cField.options[ptOpt.id]; //just make sure its not selected..
          continue;
        }
        if(pOpt.subs != null) {
          var cOpt = cField.options[pOpt.id];
          
          var subOpts = [];
          for(var j=0; j < ptOpt.subs.list.length; j++) {
            var ptSubOpt = ptOpt.subs.list[j];
            var pSubOpt = pOpt.getSubOption(ptSubOpt.id);
            if(pSubOpt != null) {
             var qty = cField.selectedOptionQty(pOpt.id, ptSubOpt.id);
             subOpts.push('<li id="' + idPrefix + 'ms_' + ptSubOpt.id + '">' +
               '<label>' + ptSubOpt.value + '</label><input id="' + idPrefix + 'mqs_' + ptSubOpt.id + '" style="width: 25px;" type="text" ' + (renderEvents ? 'onkeyup="d.multiQtyChange(this, ' + this.id + ', ' + ptOpt.id + ',' + ptSubOpt.id + ');"' : '') + ' value="' + qty + '"' + en + '/>' +
                '</li>');
            }
          }
          if(subOpts.length > 0) {
            opts.push('<li id="' + idPrefix + 'm_' + ptOpt.id + '" class="block">' +
                  '<label>' + ptOpt.value + '</label><ul>' + subOpts.join("\n") + '</ul>' +
                '</li>');
          }
        } else {
          var qty = cField.selectedOptionQty(pOpt.id);
          opts.push('<li id="' + idPrefix + 'm_' + ptOpt.id + '">' +
            '<label>' + ptOpt.value + '</label><input id="' + idPrefix + 'mq_' + ptOpt.id + '" style="width: 25px;" type="text" ' + (renderEvents ? 'onkeyup="d.multiQtyChange(this, ' + this.id + ', ' + ptOpt.id + ');"' : '') + ' value="' + qty + '"' + en + '/>' +
                '</li>');
        }
      }
      
    }
    
    return '<div id="' + idPrefix + 'multi_container_' + this.id + '" ' + dis + ' class="multi_qty_tr">' +
            '<ul>' + opts.join("\n") + '</ul>' +
          '</div>';
  },
  
  renderCheckRadio: function PTF_renderCheckRadio(cProduct, pField, cField) {
    log("renderCheckRadio");
    var disCode = (d.mode == DESIGNER_MODE_AMEND && this.priceModifierType != PRICE_MODIFY_NONE) ? ' disabled="true"' : '';
    var oRef = cField.objectRef();
    var opts = [];
    for(var i=0; i < this.options.list.length; i++) {
      var ptOpt = this.options.list[i];
      if(!ptOpt.isMulti) {
        var pOpt = pField.options.byId[ptOpt.id];
        if(pOpt != null) {
          
          var subHtml = '';
          if(pOpt.subs != null) {
            var pSel = cField.selectedOptionQty(pOpt.id) > 0;
            var subDis = pSel ? '' : ' style="display:none;"';
        
            var subOpts = [];
            for(var j=0; j < ptOpt.subs.list.length; j++) {
              var ptSubOpt = ptOpt.subs.list[j];
              var pSubOpt = pOpt.getSubOption(ptSubOpt.id);
              if(pSubOpt != null) {
                var subSel = cField.selectedOptionQty(pOpt.id, ptSubOpt.id) > 0;
                var selHtml = subSel ? ' checked="true"' : '';
                var elHtml = null;
                if(this.fieldType == FIELD_TYPE_LIST_CHECKBOX) {
                  elHtml='<input type="checkbox" ' + selHtml + ' id="so_' + ptSubOpt.id + '" onclick="' + oRef +'.selectValue(this.checked, ' + ptOpt.id + ',' + ptSubOpt.id + ');"/>';
                } else {
                  elHtml='<input type="radio" ' + selHtml + ' name="sub_' + ptOpt.id + '" id="so_' + ptSubOpt.id + '" onclick="' + oRef +'.selectValue(this.checked, ' + ptOpt.id + ',' + ptSubOpt.id + ');"/>';
                }
                subOpts.push('<li>' + elHtml + '<label>' + ptSubOpt.name + '</label></li>');
              }
            }
            if(subOpts.length > 0) {
              subHtml = '<ul id="subs_' + ptOpt.id + '"' + subDis + '>' + subOpts.join("\n") + '</ul>';
            }
          }
          var sel = cField.selectedOptionQty(pOpt.id) > 0;
          var selHtml = sel ? ' checked="true"' : '';
          var elHtml = null;
          if(this.fieldType == FIELD_TYPE_LIST_CHECKBOX) {
            elHtml='<input type="checkbox" ' + selHtml + ' id="o_' + ptOpt.id + '" onclick="' + oRef +'.selectValue(this.checked, ' + ptOpt.id  + ');"/>';
          } else {
            elHtml='<input type="radio" ' + selHtml + ' name="fo_' + this.id + '" id="o_' + ptOpt.id + '" onclick="' + oRef +'.selectValue(this.checked, ' + ptOpt.id + ');"/>';
          }
              
          var qty = cField.selectedOptionQty(pOpt.id);
          opts.push('<li id="m_' + ptOpt.id + '">' + elHtml + '<label>' + ptOpt.name + '</label>' + subHtml + '</li>');
        }
      }
    }
    return '<ul>' + opts.join("\n") + '</ul>';
    
    
  },
  
  //when the product does not have a default on field we need to init the options from what is default on...
  getProductDefaultOptions: function PTF_getProductDefaultOptions() {
    var opts = [];
    if(this.typeOptions.list) {
      for(var i=0; i < this.options.list.length; i++) {
        var ptOpt = this.options.list[i];
        if(ptOpt.defaultOn) {
          opts.push({id:ptOpt.id, d: ptOpt.defaultPrices, s: ptOpt.defaultSelected, sub: ptOpt.getDefaultSubOptions()});
        }
      }
    }
    return opts;
  }
  
});

var ProductTypeOption = Class.create({
    CLASSDEF: {
        name: 'ProductTypeOption'
    },
  
  initialize: function PTO_initialize(id, options, field) {
    this.id = id;
    this.name = options.n;
    this.value = options.c;
    this.isMulti = options.m;
    this.defaultPrices = options.pta;
    this.field = field;
    this.defaultOn = options.defo;
    this.defaultSelected = options.defs;
    if(options.sub != null) {
      this.subs = new MapList(this);
      for(var i=0; i < options.sub.length; i++) {
        this.subs.add(new ProductTypeSubOption(options.sub[i], this));
      }
    } else {
      this.subs = null;
    }
  },
  
  getDelta: function PTO_getDelta(product, color_type) {
    var fc = product.optionsByPoId[this.id];
    if(fc != null) {
      return fc.delta[color_type];
    }
    return 0;
  },
  
  getFieldChoice: function PTO_getFieldChoice(product) {
    return product.optionsByPoId[this.id];
  },
  
  getSubOption: function PTO_getSubOption(subOptId) {
    if(this.subs == null) return null;
    return this.subs.byId[subOptId];
  },
  
  getDefaultSubOptions: function PTO_getDefaultSubOptions() {
    if(this.subs == null) return null;
    var opts = [];
    for(var i=0; i < this.subs.list.length; i++) {
      var ptSub = this.subs.list[i];
      if(ptSub.defaultOn) {
        opts.push({ id: ptSub.id, s: ptSub.defaultSelected, d: ptSub.defaultPrices});
      }
    }
    return opts;
  }
});

var ProductTypeSubOption = Class.create({
    CLASSDEF: {
        name: 'ProductTypeSubOption'
    },
  
  initialize: function PTSO_initialize(options, option) {
    this.id = options.id;
    this.name = options.n;
    this.value = options.c;
    this.defaultPrices = options.pta;
    this.option = option;
    this.defaultOn = options.defo;
    this.defaultSelected = options.defs;
  }/*,
  
  getDelta: function PTSO_getDelta(product, color_type) {
    var fc = product.optionsByPoId[this.id];
    if(fc != null) {
      return fc.delta[color_type];
    }
    return 0;
  },
  
  getFieldChoice: function PTSO_getFieldChoice(product) {
    return product.optionsByPoId[this.id];
  }*/
});

var ProductTypeProcess = Class.create({
  CLASSDEF: {
      name: 'ProductTypeProcess'
  },
  
  initialize: function PTP_initialize(productType, options) {
    this.id = options.id;
    this.process = processes.byId[options.id];
    this.priceMode = options.pm;
    this.defaultStitchCount = options.sc;
    
    this.mixing = {};
  },
  
  addMix: function PTP_addMix(otherProcessId) {
    this.mixing[otherProcessId] = processes.byId[otherProcessId];
  },
  
  getAllowedProcesses: function PTP_getAllowedProcesses(existingProcesses) {
    var result = {};
    result[this.id] = true;
    if(existingProcesses == null) {
      existingProcesses = this.mixing;
    }
    for(var k in this.mixing) {
      if(existingProcesses[k] != null) {
        result[k] = true;
      }
    }
    return result;
  }
});
