﻿YAHOO.namespace("SitNSleep.Widget");

(function() {
  var AVAILABLE = "available";
  var CHECKING = "checking";
  var UNAVAILABLE = "unavailable";
  var STORES_ONLY = "stores_only";
  var OUT_OF_STOCK = "out_of_stock";
  var UNKNOWN = "unknown";
  
  var STATES = {UNAVAILABLE: "Unavailable", UNKNOWN: "Unknown", CHECKING: "Checking", WAITING: "Waiting", CAN_SHIP: "CanShip", NO_SHIP: "NoShip" };
  var CLASSES = {UNAVAILABLE: "AvailabilityUnavailable", UNKNOWN: "AvailabilityUnknown", CHECKING: "AvailabilityChecking", WAITING: "AvailabilityUnknown", CAN_SHIP: "AvailabilityShipsTo", NO_SHIP: "AvailabilityNoShip" };
  
  YAHOO.SitNSleep.Widget.OptionsController = function(productsContainer, optionsContainer, productTags, cfg){
    cfg = (cfg) ? cfg : {};
    this.optionsWrapper = (cfg.optionsWrapper) ? new YAHOO.util.Element(cfg.optionsWrapper) : null;
    this.optionsWrapper.addClass("Hidden");
    this.productsWrapper = (cfg.productsWrapper) ? new YAHOO.util.Element(cfg.productsWrapper) : null;
    this.productsWrapper.addClass("Hidden");
    this.productsContainer = YAHOO.util.Dom.get(productsContainer);
    this.optionsContainer = YAHOO.util.Dom.get(optionsContainer);
    this.productTags = productTags;
    this.product = this.productTags[0];
    this.option = this.product.options[0];
    this.availabilityContainer = (cfg.availabilityContainer) ? new YAHOO.util.Element(cfg.availabilityContainer) : null;
    this.availabilityMessageContainer = (cfg.availabilityMessageContainer) ? new YAHOO.util.Dom.get(cfg.availabilityMessageContainer) : null;
    this.addToCartContainer = (cfg.addToCartContainer) ? new YAHOO.util.Element(cfg.addToCartContainer) : null;
    this.totalContainer = (cfg.totalContainer) ? new YAHOO.util.Element(cfg.totalContainer) : null;
    this.subTotalLabel = (cfg.subTotalLabel) ? YAHOO.util.Dom.get(cfg.subTotalLabel) : null;
    this.zipForm = (cfg.zipForm) ? YAHOO.util.Dom.get(cfg.zipForm): null;
    this.zipFormButton = (cfg.zipFormButton) ? YAHOO.util.Dom.get(cfg.zipFormButton): null;
    this.zipField = (cfg.zipField) ? YAHOO.util.Dom.get(cfg.zipField): null;
    this.shippingCheckContainer = (cfg.shippingCheckContainer) ? new YAHOO.util.Element(cfg.shippingCheckContainer) : null;
    this.locationsUrl = (cfg.locationsUrl) ? cfg.locationsUrl : "/locations";
    this.phoneNumber = (cfg.phoneNumber) ? cfg.phoneNumber : "/locations";
    
    
    YAHOO.util.Event.addListener(this.zipFormButton, "click", this.handleZipButtonEvent, this, true);
    YAHOO.util.Event.addListener(this.zipField, "keydown", this.handleZipFieldEvent, this, true);
    
    this.updateSubTotal();
    this.buildProducts(this.productTags);
    this.buildOptions(this.product.options, (this.product.available));
    
    this.setState(STATES.UNKNOWN);
  };

  YAHOO.SitNSleep.Widget.OptionsController.prototype = {
    
    setZip: function(zip){
        if(this.state != STATES.UNAVAILABLE && this.state != STATES.UNKNOWN){
            if(null != zip && "" != zip){
                this.zip = zip;
                this.setState(STATES.CHECKING);
                this.checkZip(this.zip, this.product, this.option);
            }            
        }
    },
    
    handleZipSuccess: function(){
        if(this.state == STATES.CHECKING){
            this.setState(STATES.CAN_SHIP);
        }
    },
    
    handleZipFailure: function(){
        if(this.state == STATES.CHECKING){
            this.setState(STATES.NO_SHIP);
        }
    },
    
    checkAvailability: function(){
        if(this.state == STATES.UNKNOWN){
            if(this.product.available && (null == this.option || this.option.available)){
                this.setState(STATES.WAITING);
            }
            else{
                this.setState(STATES.UNAVAILABLE);
            }
        }
    },
    
    changeOption: function(option){
        this.option = option;
        this.updateSubTotal();
        this.setState(STATES.UNKNOWN);
    },
    
    changeProduct: function(product){
        this.product = product;
        this.showOptionsForProduct();
        this.updateSubTotal();
        this.setState(STATES.UNKNOWN);
    },
    
    setState: function(state){
        switch(state){
            case STATES.WAITING:
                this.state = STATES.WAITING;
                this.setDisplay(STATES.WAITING);
                if(null != this.zip && "" != this.zip){
                    this.setZip(this.zip);
                }
                break;
            case STATES.CAN_SHIP:
                this.state = STATES.CAN_SHIP;
                this.setDisplay(STATES.CAN_SHIP);
                break;
            case STATES.NO_SHIP:
                this.state = STATES.NO_SHIP;
                this.setDisplay(STATES.NO_SHIP);
                break;
            case STATES.CHECKING:
                this.state = STATES.CHECKING;
                this.setDisplay(STATES.CHECKING);
                break;
            case STATES.UNKNOWN:
                this.state = STATES.UNKNOWN;
                this.setDisplay(STATES.UNKNOWN);
                this.checkAvailability();
                break;
            case STATES.UNAVAILABLE:
                this.state = STATES.UNAVAILABLE;
                this.setDisplay(STATES.UNAVAILABLE);
                break;
        }
    },
    
    setDisplay: function(state){
    
        this.addToCartContainer.removeClass("Hidden");
        this.totalContainer.removeClass("Hidden");
        this.shippingCheckContainer.removeClass("Hidden");
        this.availabilityContainer.removeClass(CLASSES.CAN_SHIP);
        this.availabilityContainer.removeClass(CLASSES.CHECKING);
        this.availabilityContainer.removeClass(CLASSES.NO_SHIP);
        this.availabilityContainer.removeClass(CLASSES.UNAVAILABLE);
        this.availabilityContainer.removeClass(CLASSES.UNKNOWN);
        this.availabilityContainer.removeClass(CLASSES.WAITING);
        
        switch(state){
            case STATES.WAITING:
                this.availabilityContainer.addClass(CLASSES.WAITING);
                this.availabilityMessageContainer.innerHTML = "Enter a zip code to check availability:";
                break;
            case STATES.CAN_SHIP:
                this.availabilityContainer.addClass(CLASSES.CAN_SHIP);
                this.availabilityMessageContainer.innerHTML = "Available to ship to <span>" + this.zipCode + "</span>";
                break;
            case STATES.NO_SHIP:
                this.availabilityContainer.addClass(CLASSES.NO_SHIP);
                this.addToCartContainer.addClass("Hidden");
                this.availabilityMessageContainer.innerHTML = "Does not ship to zip code: <span>" + this.zipCode + "</span>";
                break;
            case STATES.CHECKING:
                this.availabilityContainer.addClass(CLASSES.CHECKING);
                this.availabilityMessageContainer.innerHTML = "Checking Availability";
                break;
            case STATES.UNKNOWN:
                this.availabilityContainer.addClass(CLASSES.UNKNOWN);
                this.availabilityMessageContainer.innerHTML = "Enter a zip code to check availability:";
                break;
            case STATES.UNAVAILABLE:
                this.availabilityContainer.addClass(CLASSES.UNAVAILABLE);
                this.totalContainer.addClass("Hidden");
                this.addToCartContainer.addClass("Hidden");
                this.shippingCheckContainer.addClass("Hidden");
                this.availabilityMessageContainer.innerHTML = "<strong>Not Available Online</strong> - call us at <strong style='white-space:nowrap;'>" + this.phoneNumber + "</strong> or visit one of <span><a href='" + this.locationsUrl + "'>our locations</a></span>";
                break;
        }
    },
  
  
    handleProductClick: function(ev, index){
        this.changeProduct(this.productTags[index]);
    },
    
    handleOptionClick: function(ev, option){
        this.changeOption(option);
    },
    
    handleZipButtonEvent: function(ev){
        YAHOO.util.Event.preventDefault(ev);
        this.setZip(this.zipField.value);
    },
    
    handleZipFieldEvent: function(ev){
        if(13 == ev.keyCode){
            YAHOO.util.Event.preventDefault(ev);
            this.setZip(this.zipField.value);
        }
    },
    
    updateSubTotal: function(){
      var total = 0.0;
      if(this.product && this.product.price){
          total += parseFloat(this.product.price);
      }
      if(this.option && this.option.price){
          total += parseFloat(this.option.price);
      }
      this.subTotalLabel.innerHTML = YAHOO.util.Number.format(total, {prefix: "$", decimalPlaces : 2, decimalSeparator : "."});
    },
    
    buildProducts: function(productTags){
      var selectedTitle = (this.selectedProduct) ? this.selectedProduct.title : null;
      this.selectedProduct = null;
      var selectedIndex = 0;
      
      if(0 == productTags.length){
        this.productsWrapper.addClass("Hidden");
      }else{
        this.productsWrapper.removeClass("Hidden");
      }
      
      for(var i=0;i<productTags.length;i++){
        if(productTags[i].title == selectedTitle){
            this.selectedProduct == productTags[i];
            selectedIndex = i;
        }
      }
      
      this.selectedProduct = productTags[selectedIndex];
      
      var productsHTML = "<table><tbody>";
      for(var i=0;i<productTags.length;i++){
        var fieldId = YAHOO.util.Dom.generateId();
        productTags[i].fieldId = fieldId;
        productsHTML += this.buildField(productTags[i], "productId", (selectedIndex == i), (productTags[i].available/* && productTags[i].inStock*/));
      }
      
      for(var i=0;i<productTags.length;i++){
        YAHOO.util.Event.addListener(productTags[i].fieldId, "click", this.handleProductClick, i, this);
      }
      productsHTML += "</tbody></table>";
      this.productsContainer.innerHTML = productsHTML;
    },
    
    buildOptions: function(optionTags, enabled){
    
      var selectedTitle = (this.option) ? this.option.title : null;
      this.option = null;
      var selectedIndex = 0;
      
      if(0 == optionTags.length){
        this.optionsWrapper.addClass("Hidden");
      }else{
        this.optionsWrapper.removeClass("Hidden");
      }
      
      for(var i=0;i<optionTags.length;i++){
        if(optionTags[i].title == selectedTitle){
            this.option == optionTags[i];
            selectedIndex = i;
        }
      }
      
      this.option = optionTags[selectedIndex];
      var optionsHTML = "<table><tbody>";
      for(var i=0;i<optionTags.length;i++){
        var fieldId = YAHOO.util.Dom.generateId();
        optionTags[i].fieldId = fieldId;
        optionsHTML += this.buildField(optionTags[i], "optionId", (selectedIndex == i), enabled);
      }
      
      optionsHTML += "</tbody></table>";
      this.optionsContainer.innerHTML = optionsHTML;
      
      for(var i=0;i<optionTags.length;i++){
        YAHOO.util.Event.addListener(optionTags[i].fieldId, "click", this.handleOptionClick, optionTags[i], this);
      }
      
    },
    
    showOptionsForProduct: function(){
      this.buildOptions(this.product.options, (this.product.available/* && this.product.inStock*/));
    },
    
    buildField: function(product, fieldName, selected, enabled){
      return "<tr class=\""
        + ((product.available) ? "Available" : "Unavailable")
        + "\"><td><label><input id=\""
        + product.fieldId
        + "\""
        + ((selected) ? " checked=\"checked\"" : "")
        + ((enabled && product.available /*&& product.inStock*/) ? "" : " disabled=\"disabled\"")
        + " name=\""
        + fieldName
        + "\" type=\"radio\" value=\""
        + product.id
        + "\" />"
        + product.title
        + "</label></td><td class='Number'>"
        + ((0.0 < parseFloat(product.price)) ? YAHOO.util.Number.format(product.price, {prefix: "$", decimalPlaces : 2, decimalSeparator : "."}) : "")
        + "</td></tr>";
    },
    
    checkZip: function(){
        this.zipCode = this.zipField.value;
        if(this.zipCode && this.zipCode != ""){
            this.shipsTo = CHECKING;
            var callback =
            {
              success: this.handleZipCheck,
              failure: this.handleZipCheck,
              scope:this
            }
            YAHOO.util.Connect.setForm(this.zipForm);
            var cObj = YAHOO.util.Connect.asyncRequest('GET', "/util/available-for-zip-code?", callback); 
        }
    },
    
    handleZipCheck: function(response){
        if(response.responseText == "true"){
            this.handleZipSuccess();
        }
        else{
            this.handleZipFailure();
        }
    },
    
    
    setZipCookie: function(zipCode){
      var expirationDate = new Date();
      expirationDate.setDate(expirationDate.getDate()+365); //expires one year from now
      YAHOO.util.Cookie.set("zipCode", zipCode, { 
        expires: expirationDate
      }); 
    },
    
    getZipCookie: function(){
      return YAHOO.util.Cookie.get("zipCode");
    }
    
  };
  
  
})();
