//a place to store selction info about a field.. handles multiselect
var ConfiguredField = Class.create({
  CLASSDEF: {
      name: 'ConfiguredField'
  },
  
  initialize: function CPF_initialize(id, configuredProduct, options) {
    this.id = id;
    this.configuredProduct = configuredProduct;
    this.options = {}; //hash of ConfiguredFieldOption objects
    
    this.usePriceDefaults = options.uDef;
    
    this.multiSelect = false;
    this.multiOption = null;
    this.productField = this.configuredProduct.product.fields.byId[this.id];
    this.fieldDef = this.productField.fieldDef;
    if(this.fieldDef==null) {
      return;
    }
    this.fieldValue = null;
    if(options != null) {
      if(options.val != null) {
        if(this.fieldDef.typeOptions.date) {
          try {
            this.fieldValue = new Date(options.val);
          } catch(e) {
            log("Error parsing date '" + options.val + "' when loading " + this.fieldDef.name);
          }
        } else {
          this.fieldValue = options.val;
        }
      }
    }
   
      
  },
  
  
  addSelectedOption: function CPF_addSelectedOption(optionId, qty, subOptionId) {
    var opt = this.options[optionId];
    var subQty = 0;
    if(subOptionId != null) {
      subQty = qty;
      qty = 1;
    }
    if(opt == null) {
      opt = new ConfiguredFieldOption(this, optionId, qty);
      if((opt.def == null)||(opt.pDef == null)) {
        log("Dropping option " + optionId + " as it has no def");
        return null;
      }
      this.options[optionId] = opt;
    } else {
      opt.qty = qty;
    }
    
   
    
    if(opt.def.isMulti) {
      this.multiSelect = true;
      this.multiOption = opt;
    } else if(subOptionId != null) {
      opt.addSelectedOption(subOptionId, subQty);
    }
    return opt;
  },
  
  //used when qty get set to 0 on sub option: remove the option...
  cleanEmptyOptions: function CPF_cleanEmptyOptions() {
    for(var k in this.options) {
      var opt = this.options[k];
      if((opt.qty == 0)||( (opt.def.subs != null) && (opt.subQty == 0)) ) {
        delete this.options[k];
      }
    }
  },
  
  initToDefault: function CPF_initToDefault() {
    if(this.fieldDef.typeOptions.list) {
      if(hashFirstElement(this.options) == null) { //no selected option...
        log("Initializing " + this.fieldDef.name + " to default");
        for(var i=0; i < this.productField.options.list.length; i++) {
          var pOpt = this.productField.options.list[i];
          if(pOpt.selected) {
            log("Adding default option " + pOpt.def.name);
            var opt = this.addSelectedOption(pOpt.id, 1);
            opt.initToDefault();
          }
        }
      }
      //check if this field is only is multi select mode...
      if(this.fieldDef.fieldType == FIELD_TYPE_PRODUCT_SIZE && this.fieldDef.productType.ms && !this.multiSelect && !this.configuredProduct.product.usesMinQty()) {
        log("Adding multiselect option because field is in multi only mode");
        this.addSelectedOption(this.fieldDef.multiOption.id, 1, null); //add the multi option...
      }
    }
  },
  
  selectedOptionQty: function CPF_selectedOptionQty(optionId, subOptionId) {
    var qo = this.options[optionId];
    if(qo == null) return 0;
    if(subOptionId != null) {
      var so = qo.subOptions[subOptionId];
      if(so==null) return 0;
      return so.qty;
    } else {
      return qo.qty;
    }
  },
  
  getMainOption: function CPF_getMainOption(useDefault, allowMultiSelect) {
    if(useDefault == true && hashFirstElement(this.options) == null) {
      if(this.productField.defaultOption == null) {
        return null;
      }
      this.addSelectedOption(this.productField.defaultOption.id, 1);
    }
    if((this.multiSelect)&&(allowMultiSelect != false)) {
      return this.multiOption;
    } else {
      for(var k in this.options) {
        return this.options[k]; //just return the first option
      }
      //no option selected... lets add the default
      if (useDefault == true) {
        return this.addSelectedOption(this.productField.defaultOption.id, 1);
        //return this.productField.defaultOption;
      }
      return null;
    }
  },
  
  //called when user changes field value from interface
  setValue: function CPF_setValue(value, valueType) {
    if(this.fieldDef.typeOptions.list) { //the value is an option....
      if(value == null && this.fieldDef.fieldType == FIELD_TYPE_LIST_MULTISELECT) {
        //multi values from the form field
        this.options = {}; //reset as we will reload all from el
        this.multiSelect = false;
        this.multiOption = null;
    
        var el = $(this.iId('value'));
        if(el != null) {
          for(var i=0; i < el.length; i++) {
            if(el.options[i].selected) {
              var ids = this.extractOptIds(el.options[i].value);
              this.addSelectedOption(ids[0], 1, ids[1]);
            }
          }
        }
      } else {
        this.setListValue(value, valueType);
      }
      if(this.fieldDef.fieldType == FIELD_TYPE_PRODUCT_SIZE && this.configuredProduct.product.limitSizeColors) {
        //we need to rerender the color list as the size selection could have changed available colors..
        this.configuredProduct.product.type.buildColorPanel(this.configuredProduct);
      }
    } else if(this.fieldDef.fieldType == FIELD_TYPE_TEXT_BOX || this.fieldDef.fieldType == FIELD_TYPE_TEXT_AREA)  {
      this.fieldValue = value;
    } else if(this.fieldDef.fieldType == FIELD_TYPE_FILE || this.fieldDef.fieldType == FIELD_TYPE_IMAGE)  {
      //check that that file is valid
      var el = $(this.iId('value'));
      if(!this.validFile(el.value)) {
        alert(ml("You can only upload files of type: %s", this.fieldDef.customOption("extensions", '')));
        el.value = "";
        return;
      }
      //we need to submit the form field after popping up the upload status bar...
      startAsyncAction(); 
      startTrackingUpload("CF"); 
      
      $("field_upload_form" + this.fieldDef.id).submit();
      popup("field_upload_popup");
    } else if((this.fieldDef.fieldType == FIELD_TYPE_DATE)||(this.fieldDef.fieldType == FIELD_TYPE_DATE_TIME)) {
      this.fieldValue = this.loadDateFromInputs(true, (this.fieldDef.fieldType == FIELD_TYPE_DATE_TIME));
    } else if(this.fieldDef.fieldType == FIELD_TYPE_TIME) {
      this.fieldValue = this.loadDateFromInputs(false, true);
    }
    d.track("change-" + this.fieldDef.name);
    this.configuredProduct.product.type.updatePrice();
    d.itemChanged();
  },
  
  loadDateFromInputs: function CPF_loadDateFromInputs(do_date, do_time) {
    var date = new Date();
    var selVal = null;
    try {
      if(do_date) {
        //month
        selVal = $FV(this.iId("date_1"));
        if(selVal == null || selVal == "") return null;
        date.setMonth(selVal);
        //day
        selVal = $FV(this.iId("date_0"));
        if(selVal == null || selVal == "" || isNaN(selVal)) return null;
        var iVal = parseInt(selVal, 10);
        if(iVal < 1 || iVal > 31) return null;
        date.setDate(iVal);
        //year
        selVal = $FV(this.iId("date_2"));
        if(selVal == null || selVal == "") return null;
        date.setFullYear(selVal);
      }
      if(do_time) {
        var timeFormat = parseInt(this.customOption("time_format", '0'), 10);
        //hour
        var timeMod = 0;
        if(timeFormat == 0) {
          timeMod = ($FV(this.iId("date_5")) == "AM")? 0 : 12;
          selVal = $FV(this.iId("date_3"));
        } else {
          selVal = $FV(this.iId("date_6"));
        }
        if(selVal == null || selVal == "" || isNaN(selVal)) return null;
        var iVal = parseInt(selVal, 10);
        if(iVal < 0 || iVal > 23) return null;
        date.setHours(iVal + timeMod);
        
        //minute
        selVal = $FV(this.iId("date_4"));
        if(selVal == null || selVal == "" || isNaN(selVal)) return null;
        var iVal = parseInt(selVal, 10);
        if(iVal < 0 || iVal > 59) return null;
        date.setMinutes(iVal);
      }
      
    } catch(e) {
      log("Exception when loading date:" + e.getMessage());
      return null;
    }
    return date;
  },
  
  validFile: function CPF_validFile(filename) {
    var ext = this.fieldDef.customOption("extensions", null);
    if((ext == null)||(ext.length==0)) return true;
    var exts = ext.split(' ');
    if(exts.length == 0) return true;
    for(var i=0; i < exts.length; i++) {
      var ext = exts[i];
      var extLength = ext.length;
      if((filename.length > extLength + 1)&&(filename[filename.length - extLength - 1] == '.')) {
        var fileTest = filename.substr(filename.length - extLength, extLength);
        if(fileTest.toLowerCase() == ext.toLowerCase()) {
          return true;
        }
      }
    }
    return false;
  },
  
  uploadFinished: function CPF_uploadFinished(fileData) {
    closePopup("field_upload_popup");
    if(fileData.error != null) {
      alert(fileData.error);
      return;
    }
    this.fieldValue = fileData;
    this.fieldValue.isWorkingVersion = true;
    this.fieldDef.setField(this.configuredProduct); //rerender the field so it now shows the uploaded file...
  },
  
  removeFile: function CPF_removeFile() {
    if(confirm(ml("Are you sure you want to remove this file?"))) {
      this.fieldValue = null;
      this.fieldDef.setField(this.configuredProduct); //rerender the field 
    }
  },
  
  extractOptIds: function CPF_extractOptIds(value) {
    var optionId = value;
    var subOptionId = null;
    if(value.indexOf("-") != -1) { //its an option-suboption pair
      var vals = value.split('-');
      optionId = parseInt(vals[0], 10);
      subOptionId = parseInt(vals[1], 10);
      log("Identified sub option selected: " + optionId + " : "  + subOptionId);
    }
    return [optionId,subOptionId];
  },
  
  //called internally from setValue
  setListValue: function CPF_setListValue(value, valueType) {
    
    var ids = this.extractOptIds(value);
    var optionId = ids[0];
    var subOptionId = ids[1];
    
    var oldValue = this.getMainOption(true);

    this.setSelectedOption(optionId, 1, subOptionId);
    
    if(this.fieldDef.hasMulti) {
      if(this.multiSelect) { //we are now choosing a multiple select field... get the old option as make it one of the selected values
        if(oldValue != null) {
          log("Moving To MultiOption from " + oldValue.def.name + " with qty " + this.configuredProduct.qty);
          if(oldValue.subQty > 0) { //sub option was selected...
            var sub = hashFirstElement(oldValue.subOptions);
            log("Using sub option " + sub.def.name);
            this.addSelectedOption(oldValue.optionId, this.configuredProduct.qty, sub.subOptionId);
          } else {
            this.addSelectedOption(oldValue.optionId, this.configuredProduct.qty);
          }
        } else {
          log("Selected Multi Option");
        }
        this.updateMultiQty();
        this.fieldDef.showMultiQtyOptions(this);
      } else {
        log("Hiding Multi Option From CField.setValue");
        this.fieldDef.hideMultiQtyOptions(this);
      }
    } else {
      log("Selected option of field without multi option");
    }
  },
  
  updateMultiQty: function CPF_updateMultiQty() {
    for(var i=0; i < this.productField.options.list.length; i++) {
      var pOpt = this.productField.options.list[i];
      if(!pOpt.def.isMulti) {
        if(pOpt.subs != null) {
          for(var k in pOpt.subs) {
            var pSub = pOpt.subs[k];
            var el = $('mqs_' + pSub.id);
            if(el != null) {
              el.value = this.selectedOptionQty(pOpt.id, pSub.id);
            } else {
              log("Missing multi qty el for sub option " + pSub.id);
            }
          }
        } else {
          var el = $('mq_' + pOpt.id);
          if(el != null) {
            el.value = this.selectedOptionQty(pOpt.id);
          } else {
            log("Missing multi qty el for option " + pOpt.id);
          }
        }
      }
    }
  },
  
  selectDate: function PTF_selectDate(allowTime) {
    var self = this;
    var c = new CalendarDateSelect( 'field_date_value_' + this.id, {
        popup_by: 'field_date_' + this.id,
        time: allowTime,
        after_close: function() {
          self.updateDate();
          
        }
    });
  },
  
  updateDate: function(date) {
    this.fieldValue = new Date($('field_date_value_' + this.fieldDef.id).value);
    this.fieldDef.updateDate(this);
  },
  
  getValue: function CPF_getValue(defaultValue) {
    if(this.fieldValue == null) {
      return defaultValue;
    }
    return this.fieldValue;
  },
  
  //called when the field choice changes...
  //called when saving teamnames to init into mult mode...
  setSelectedOption: function CPF_setSelectedOption(optionId, qty, subOptionId, skipRecalculations) {
    //first reset the state
    this.options = {}; //hash of ProductFieldChoice objects
    this.multiSelect = false;
    this.multiOption = null;
    //then add option
    var retVal = this.addSelectedOption(optionId, qty, subOptionId);
    if(skipRecalculations != true) {
      d.track("change-" + this.fieldDef.name);
      this.configuredProduct.product.type.updatePrice();
      d.itemChanged();
    }
    return retVal;
  },
  
  //called when a checkbox/radio button is selected...
  selectValue: function CPF_selectValue(on, optionId, subOptionId) {
    log("selectValue: on=" + on + " optionId=" + optionId + " subOptionId=" + subOptionId);
    if(this.fieldDef.fieldType == FIELD_TYPE_LIST_RADIO) {//single select...
      //hide any sub option containers if needed...
      var needsShowing = true;
      for(var k in this.options) {
        var opt = this.options[k];
        if((opt.optionId != optionId)&&(opt.pDef.subs != null)) {
          var el = $("subs_" + opt.optionId);
          if(el != null) {
            el.hide();
          } else {
            log("Error: unable to get sub container for option " + opt.optionId);
          }
        } else if(opt.optionId == optionId) {
          //already showing..
          needsShowing = false;
        }
      }
      var opt = this.setSelectedOption(optionId, 1, subOptionId);
      opt.initToDefault(true, true);
      if(needsShowing) {
        var el = $("subs_" + optionId);
        if(el != null) el.show();
      }
      
    } else { //checkbox...
      if(on) {
        var opt = this.addSelectedOption(optionId, 1, subOptionId); 
        if(opt.pDef.subs != null) {
          opt.initToDefault(false, true);
          var el = $("subs_" + optionId);
          if(el != null) el.show();
        }
      } else {
        var opt = this.options[optionId];
        if(opt != null) {
          if(subOptionId != null) {
            var sOpt = opt.subOptions[subOptionId];
            delete opt.subOptions[subOptionId];
          } else {
            if(opt.pDef.subs != null) {
              var el = $("subs_" + optionId);
              if(el != null) {
                el.hide();
              } else {
                log("Error: unable to get sub container for option " + optionId);
              }
            }
            delete this.options[optionId];
          }
        } else {
          log("Error: option was not already selected " + optionId);
        }
        
      }
      
    }
    d.track("change-" + this.fieldDef.name);
    this.configuredProduct.product.type.updatePrice();
    d.itemChanged();
  },
  
  //when changing products try and tranfer accross the old selection...
  initFromPreviousSelection: function CPF_initFromPreviousSelection(old) {
    if(this.fieldDef.typeOptions.text) {
      this.fieldValue = old.fieldValue;
    } else if(this.fieldDef.typeOptions.file) {
      if(old.id == this.id) {
        this.fieldValue = old.fieldValue;
        log("Copying file field (ids are same)");
      } else {
        log("Not copying file field (" + this.id + "!=" + old.id + ")"); 
      }
    } else if(this.fieldDef.typeOptions.date) {
      this.fieldValue = old.fieldValue;
    } else if(this.fieldDef.typeOptions.list) {
      if((this.fieldDef.hasMulti)&&(old.multiSelect)) {
        log("initFromPreviousSelection: multi select chosen");
        if(this.productField.multiOption == null) {
          log("ERROR: this.fieldDef.hasMulti==true yet this.productField.multiOption is null");
        } else {
          this.setSelectedOption(this.productField.multiOption.id, 1, null, true);
          //go thru all the options this product supports
          var usedOpts = {};
          var usedSOpts = {};
          for(var k in old.options) {
            var cOpt = old.options[k];
            var opt = this.productField.findOption(cOpt.pDef);
            if(opt != null && usedOpts[opt.id] == null) {
              usedOpts[opt.id]=true; //we dont want to add some option twice (matched on different name/id/value)
              log("Found common option " + opt.def.name);
              var foundSubOptions = false;
              for(var j in cOpt.subOptions) {
                var cSOpt = cOpt.subOptions[j];
                var sOpt = opt.findOption(cSOpt.pDef);
                if((sOpt != null)&&(usedSOpts[sOpt.id] == null)) {
                  usedSOpts[sOpt.id] = true;
                  this.addSelectedOption(opt.id, cSOpt.qty, sOpt.id);
                  log("Found common sub option " + sOpt.def.name);
                  foundSubOptions=true;
                }
              }
              if(!foundSubOptions) {
                log("No Common Sub Options, using qty:" + cOpt.qty);
                this.addSelectedOption(opt.id, cOpt.qty);
              }
            }
          }
        }
      } else {
        var cOpt = old.getMainOption(true, false); //we dont want the multi option...
        if(cOpt != null) {
          var opt = this.productField.findOption(cOpt.pDef);
          if(opt != null) { //this product supports this option..
            var usingSubOpt = false;
            var cSOpt = cOpt.mainSubOption();
            if(cSOpt != null) {
              log("initFromPreviousSelection: Sub Option Previously Selected");
              var sOpt = opt.findOption(cSOpt.pDef);
              if(sOpt != null) {
                usingSubOpt = true;
                this.addSelectedOption(opt.id, 1, sOpt.id);
                log("initFromPreviousSelection: Found common sub option " + sOpt.def.name);
              }
            }
            if(!usingSubOpt) {
              this.setSelectedOption(opt.id, 1, null, true);
              log("initFromPreviousSelection: set common option " + opt.def.name);
            }
          }
        }
      }
    }
  },
  
  serialize: function CPF_serialize(queryComponents, prefix) {
    
    if(this.fieldDef.typeOptions.list) { //the value is an option....
      for(var k in this.options) {
        var cFieldOption = this.options[k];
        cFieldOption.serialize(queryComponents, prefix + "[o][" + cFieldOption.def.id + "]");
      }
    } else if(this.isUsed()) {
      if(this.fieldDef.fieldType == FIELD_TYPE_TEXT_BOX || this.fieldDef.fieldType == FIELD_TYPE_TEXT_AREA)  {
        queryComponents.push(encodeURIComponent(prefix + "[txt]") + "=" + encodeURIComponent(this.fieldValue));
      } else if(this.fieldDef.fieldType == FIELD_TYPE_FILE || this.fieldDef.fieldType == FIELD_TYPE_IMAGE)  {
        var fileSaveType = this.fieldValue.isWorkingVersion ? "2" : "1"; //track if the server should use the working version of the saved version...
        queryComponents.push(encodeURIComponent(prefix + "[file]") + "=" + encodeURIComponent(fileSaveType)); 
      } else if((this.fieldDef.fieldType == FIELD_TYPE_DATE)||(this.fieldDef.fieldType == FIELD_TYPE_DATE_TIME)||(this.fieldDef.fieldType == FIELD_TYPE_TIME)) {
        if((this.fieldDef.fieldType == FIELD_TYPE_DATE)||(this.fieldDef.fieldType == FIELD_TYPE_DATE_TIME)) {
          queryComponents.push(encodeURIComponent(prefix + "[y]") + "=" + encodeURIComponent(this.fieldValue.getFullYear()));
          queryComponents.push(encodeURIComponent(prefix + "[m]") + "=" + encodeURIComponent(this.fieldValue.getMonth()));
          queryComponents.push(encodeURIComponent(prefix + "[d]") + "=" + encodeURIComponent(this.fieldValue.getDate()));
        }
        if((this.fieldDef.fieldType == FIELD_TYPE_TIME)||(this.fieldDef.fieldType == FIELD_TYPE_DATE_TIME)) {
          queryComponents.push(encodeURIComponent(prefix + "[h]") + "=" + encodeURIComponent(this.fieldValue.getHours()));
          queryComponents.push(encodeURIComponent(prefix + "[M]") + "=" + encodeURIComponent(this.fieldValue.getMinutes()));
        }
      }
    }
    
    //log(this);
    
   //if(this.multiOption != null) {
   //  queryComponents.push(encodeURIComponent(prefix + "[o][" + this.multiOption.pcoid + "]") + "=" + encodeURIComponent(1));
   //}
  },
  
  iId: function CPF_iId(inputField, includeAttr) {
    if(includeAttr) {
      return ' id="' + this.iId(inputField, false) + '"';
    } else {
      return 'f' + inputField + '_' + this.id;
    }
  },
  
  objectRef: function CPF_objectRef() {
    return 'd.currentCProduct.cFields[' + this.id + ']';
  },
  
  getSelectedOptions: function CPF_getSelectedOptions(includeSubs) {
    var opts = [];
    for(var k in this.options) {
      var cOpt = this.options[k];
      if(!cOpt.def.isMulti) {
        cOpt.appendSelectedOptions(opts, includeSubs);
      }
    }
    return opts;
  },
  
  isUsed: function CPF_isUsed() {
    if(this.fieldValue == null) {
      return false;
    }
    return true;
  },
  
  refreshHtml: function() {
    this.fieldDef.setField(this.configuredProduct);
  }
});


var ConfiguredFieldOption = Class.create({
  CLASSDEF: {
      name: 'ConfiguredFieldOption'
  },
  
  initialize: function CPFO_initialize(field, optionId, qty) {
    this.field = field;
    this.optionId = optionId;
    this.qty = qty;
    this.pDef = field.productField.options.byId[optionId];
    this.def = field.fieldDef.options.byId[optionId];
    this.subOptions = {};
    this.subQty = 0;
  },
  
  initToDefault: function CPFO_initToDefault(mustSelect, selectElements) {
    if(hashFirstElement(this.subOptions) == null) { //no selected option...
      if(this.pDef.subs != null) {
        var anyDefault = null;
        var foundDefault = false;
        for(var k in this.pDef.subs) {
          var sub = this.pDef.subs[k];
          if(sub.selected) {
            var opt = this.addSelectedOption(sub.id, 1);
            foundDefault = true;
            if(selectElements) {
              if(opt != null) {
                var el = $('so_' + sub.id);
                if(el != null) { 
                  el.checked = true;
                } else {
                  log("Error: unable to get element to check on for sub option " + sub.id);
                }
              }
            }
          } else if(anyDefault == null){
            anyDefault = sub;
            if(selectElements) {
              var el = $('so_' + sub.id);
              if(el != null) { 
                el.checked = false;
              } else {
                log("Error: unable to get element to check on for sub option " + sub.id);
              }
 
            }
            
          }
        }
        if(!foundDefault && mustSelect && anyDefault!=null) {
          log("Forcing default value");
          var opt = this.addSelectedOption(anyDefault.id, 1);
          if(selectElements) {
            if(opt != null) {
              var el = $('so_' + anyDefault.id);
              if(el != null) { 
                el.checked = true;
              } else {
                log("Error: unable to get element to check on for sub option " + anyDefault.id);
              }
            }
          }
        }
        
      }
    }
  },
  
  addSelectedOption: function CPFO_addSelectedOption(subOptionId, qty) {
    var opt = this.subOptions[subOptionId];
    if(opt == null) {
      opt = new ConfiguredFieldSubOption(this, subOptionId, qty);
      if((opt.def == null)||(opt.pDef == null)) {
        log("Dropping sub option " + subOptionId + " as it has no def");
        return null;
      }
      this.subOptions[subOptionId] = opt;
      this.subQty += qty;
    } else {
      this.subQty += (qty - opt.qty);
      opt.qty = qty;
    }
    return opt;
  },
  
  serialize: function CPFO_serialize(queryComponents, prefix) {
    queryComponents.push(encodeURIComponent(prefix + "[q]") + "=" + encodeURIComponent(this.qty));
    if(this.subQty > 0) {
      for(var k in this.subOptions) {
        var cSubOption =  this.subOptions[k];
        cSubOption.serialize(queryComponents, prefix + "[o][" + k + "]");
      }
    }
  },
  
  appendSelectedOptions: function CPFO_appendSelectedOptions(opts, includeSubs) {
    if((this.field.fieldDef.fieldType == FIELD_TYPE_LIST_CHECKBOX)||(this.subQty==0)||(includeSubs != true)) {
      opts.push(this);
    }
    if((includeSubs==true)&&(this.subQty > 0)) {
      for(var k in this.subOptions) {
        var sOpt = this.subOptions[k];
        if(sOpt.qty > 0) {
          opts.push(sOpt);
        }
      }
    }
  },
  
  getSelectedSubOption: function CPFO_getSelectedSubOption() {
    for(var k in this.subOptions) {
      var sOpt = this.subOptions[k];
      if(sOpt.qty > 0) {
        return sOpt;
      }
    }
    return null;
  },
  
  //used to get the id of selected option when rendering combo box
  getId: function CPFO_getId() {
    if(this.subQty > 0) {
      return this.optionId + "-" + this.getSelectedSubOption().subOptionId;
    } else {
      return this.optionId;
    }
  },
  
  mainSubOption: function() {
    return hashFirstElement(this.subOptions);
  }
    
});

var ConfiguredFieldSubOption = Class.create({
  CLASSDEF: {
      name: 'ConfiguredFieldSubOption'
  },
  
  initialize: function CPFSO_initialize(option, subOptionId, qty) {
    this.option = option;
    this.field = option.field;
    this.subOptionId = subOptionId;
    this.qty = qty;
    this.def = option.def.getSubOption(subOptionId);
    this.pDef = option.pDef.getSubOption(subOptionId);
  },
  
  serialize: function CPFO_serialize(queryComponents, prefix) {
    queryComponents.push(encodeURIComponent(prefix + "[q]") + "=" + encodeURIComponent(this.qty));
  }
});
