/*
 * Product "class" in that screwed up javascript way
 * we have adopted our own convention that class constructors will be ucfirst
 * but all instances will be lower-end-camel-case because there basically are no primitive
 * types in javascript anyway
 *
 * NB: when doing the foreach equivalent in JavaScript:
 *
 *   for (var i in this.colours)
 *
 * you must check that the index is actually a number, or you'll get all kinds of crazy things
 * happening. (Arrays are objects and also contain functions, which will be referenced in the
 * loop.)
 */
function Product(product, variation_props, defaultImage, defaultZoomify)
{
  // -----------------------------------------------------------
  // properties
  // -----------------------------------------------------------
  this.product              = product;
  this.variation_properties = variation_props;
  this.defaultImage         = defaultImage;
  this.defaultZoomify       = defaultZoomify;
      
  this.colours = [];
  this.selected_colour_id = 0;
   // -----------------------------------------------------------

  
  // -----------------------------------------------------------
  // methods
  // -----------------------------------------------------------
  this.associateColours         = associateColours;
  this.associateSizes           = associateSizes;
  this.createSwatches           = createSwatches;
  this.getItemId                = getItemId;
  this.getNumberOfProperties    = getNumberOfProperties;
  this.preloadImage             = preloadImage;
  this.populateProduct          = populateProduct;
  this.populateProductAttribute = populateProductAttribute;
  this.restoreProduct           = restoreProduct;
  this.setSelectedColour        = setSelectedColour;
  this.showMaster               = showMaster;
  this.validateAdd              = validateAdd;
  // -----------------------------------------------------------


  // Initialising
  // -----------------------------------------------------------

  // Preload the main product image.
  this.preloadImage(this.product.image); 
  
  // Add the swatches to the interface.
  this.createSwatches();
  
  // Show the master image for the product by default.
  this.showMaster();
  
  
  
  /**
   * Associate the product colours with their images and swatches.
   */
  function associateColours()
  {
    for (var i in this.product.variations)
    {
      if (i == Number(i))
      {
        var variation  = this.product.variations[i];
        
        var colour_id  = variation.variation_value_1_id;
        var colour_key = this.variation_properties[0].options[colour_id];
        
        if (this.colours[colour_id] == undefined)
        {
          this.colours[colour_id]            = [];
        }
        this.colours[colour_id]['name']      = colour_key;
        this.colours[colour_id]['swatch']    = variation.swatch_hex;
        this.colours[colour_id]['image']     = variation.image;
        this.colours[colour_id]['big_image'] = variation.big_image;
        this.colours[colour_id]['variation_id'] = variation.id;
        this.colours[colour_id]['variation_image_id'] = variation.variation_image_id;
        this.colours[colour_id]['variation_zoomify_image'] = variation.variation_zoomify_image;
                
        if (this.colours[colour_id]['enabled'] != undefined)
        {
          this.colours[colour_id]['enabled']   = Boolean(this.colours[colour_id]['enabled']) || Boolean(variation.status);
        }
        else
        {
          this.colours[colour_id]['enabled']   = Boolean(variation.status);
        }
        
        this.preloadImage(variation.image);
        this.preloadImage(variation.big_image);
      }
    }
  }


  /**
   * Associate the product colours with their available sizes.
   */
  function associateSizes()
  {
    for (var i in this.product.variations)
    {
      if (i == Number(i))
      {
        var variation = this.product.variations[i];
        var colour_id = variation.variation_value_1_id;
        var size_id   = variation.variation_value_2_id;
        var size_text = this.variation_properties[1].options[size_id];
        
        if (this.colours[colour_id]['sizes'] == undefined)
        {
          this.colours[colour_id]['sizes']          = [];
        }
        this.colours[colour_id]['sizes'][size_id] = []
        this.colours[colour_id]['sizes'][size_id]['text']    = size_text;
        this.colours[colour_id]['sizes'][size_id]['enabled'] = Boolean(variation.status);
      }
    }
  }
  
  
  /**
   * Get a variation ID for specified attributes.
   */
  function getItemId(variation_1_id, variation_2_id)
  {
    for (var i in this.product.variations)
    {
      if (i == Number(i))
      {
        var variation = this.product.variations[i];
        if ((variation_1_id == variation.variation_value_1_id) &&
            (variation_2_id == variation.variation_value_2_id))
        {
          return variation.id;
        }
      }
    }
    return false;
  }
  
  
  /**
   * Create swatch links for selecting the product colour.
   */
  function createSwatches()
  {
    // First get a list of all the possible swatches.
    this.associateColours();
    this.associateSizes();
    
    // Generate some HTML for each swatch.
    var table      = document.createElement('table');
    var table_body = document.createElement('tbody');
    var table_row  = document.createElement('tr');
        
    for (var colour_id in this.colours)
    {
      if (colour_id == Number(colour_id))
      {
        var table_cell = document.createElement('td');
        if (this.colours[colour_id]['enabled'] == false)
        {
          table_cell.className = 'disabled';
        }
        table_cell.onmouseover = new Function('product.populateProduct(' + colour_id + ', false);');
        table_cell.onmouseout  = new Function('product.restoreProduct();');
        
        var swatch = document.createElement('a');
        swatch.className = 'swatch';
        swatch.setAttribute('href', 'javascript:void(0)');
        swatch.setAttribute('id', 'variationSwatch_' + colour_id);
        swatch.style.backgroundColor = '#' + this.colours[colour_id]['swatch'];
        if (this.colours[colour_id]['enabled'])
        {
          swatch.onclick = new Function('product.populateProduct(' + colour_id + ', true);');
        }
        else
        {
          swatch.onclick = new Function('alert(\'This colour is not available at present; please select a different one.\');');
        }
        table_cell.appendChild(swatch);
        table_row.appendChild(table_cell);
      }
    }
    
    // Display the colour name.
    var colour_name = document.createElement('td');
    colour_name.setAttribute('id', 'color_name');
    table_row.appendChild(colour_name);
    
    // Add the tabel to the placeholder.
    table_body.appendChild(table_row);
    table.appendChild(table_body);
    $('product-attributes-swatches').appendChild(table);
  }


  /**
   * A small local function for preloading images.
   */
  function preloadImage(filename)
  {
    var image = new Image();
    image.src = filename;
  }


  /**
   * Gets the number of variation properties.
   */
  function getNumberOfProperties()
  {
    var count = 0;
    for (var i = 0; i < 3; i++)
    {
      if (this.variation_properties[i].name != undefined)
      {
        count++;
      }
    }
    return count;
    
  }


  /**
   * Show the master image and the main product properties.
   */
  function showMaster()
  {
    this.populateProductAttribute('image-thumb-object', 'src', this.product.image);
    this.populateProductAttribute('image-zoom-object', 'src', this.product.big_image);
    this.populateProductAttribute('color_name', 'innerHTML', 'none');
    if(this.defaultZoomify == 1)
    {
      $('image-thumb-object-link-zoom').removeClassName('enlarge');
      $('image-thumb-object-link-zoom').addClassName('super-zoom');  
      $('image-thumb-object-link-zoom').onclick = popupImage.bind(this, '/shop/page-product_popup/action-product_popup.zoomify/product_id-' + this.product.id + '/variation_image_id-' + this.defaultImage, 750, 750);  
    }
    else
    {
      $('image-thumb-object-link-zoom').removeClassName('super-zoom');
      $('image-thumb-object-link-zoom').addClassName('enlarge');  
      $('image-thumb-object-link-zoom').onclick = popupImage.bind(this, '/shop/page-product_popup/action-product_popup.zoom/product_id-' + this.product.id + '/variation_id-' + this.defaultImage, 650, 750);  
    }
  }
  

  /**
   * Show a variation image and its properties.
   */
  function populateProduct(colour_id, set_as_selected)
  {
    this.populateProductAttribute('image-thumb-object', 'src', this.colours[colour_id]['image']);
    
    this.populateProductAttribute('color_name', 'innerHTML', this.colours[colour_id]['name']);
    
    if (this.colours[colour_id].variation_zoomify_image == 1)
    {
      $('image-thumb-object-link-zoom').removeClassName('enlarge');
      $('image-thumb-object-link-zoom').addClassName('super-zoom');
      $('image-thumb-object-link-zoom').onclick = popupImage.bind(this, '/shop/page-product_popup/action-product_popup.zoomify/product_id-' + this.product.id + '/variation_image_id-' + this.colours[colour_id].variation_image_id, 750, 750); 
    }
    else
    {
      $('image-thumb-object-link-zoom').removeClassName('super-zoom');
      $('image-thumb-object-link-zoom').addClassName('enlarge');
      $('image-thumb-object-link-zoom').onclick = popupImage.bind(this, '/shop/page-product_popup/action-product_popup.zoom/product_id-' + this.product.id + '/variation_id-' + this.colours[colour_id].variation_id, 600, 770);
    }
   
    if (set_as_selected)
    {
      this.setSelectedColour(colour_id);
      showMeasurementsIn(getCookie('product_measurement'));
    }
  }


  /**
   * Sets the attribute value of a specified HTML page element.
   */
  function populateProductAttribute(element, domAttribute, value)
  { 
    try {
      $(element)[domAttribute] = value;
    } catch (err) {
      // don't do anything
    }
  }


  /**
   * Displays the currently selected variation, or the main product information if no variations
   * are selected. Usually used on a swatch's onmouseout() attribute.
   */
  function restoreProduct()
  {
    if (this.selected_colour_id)
    {
      this.populateProduct(this.selected_colour_id, false);
    }
    else
    {
      // no variation set, so restore master
      this.showMaster();
    }
  }
  

  /**
   * Sets a specific colour as the selected one, and (when applicable) show the available sizes.
   */
  function setSelectedColour(colour_id)
  {
    // Update the selected colour if it isn't the same as the previously selected one.
    if (this.selected_colour_id > 0 && this.selected_colour_id != colour_id)
    {
      $('variationSwatch_' + this.selected_colour_id).removeClassName('selected');
    }
    $('variationSwatch_' + colour_id).addClassName('selected');
    this.selected_colour_id = colour_id;

    var container        = $('variationsContainer');    
    var button_container = $('size-interface');
    var variation        = this.colours[colour_id];
    
    if (this.getNumberOfProperties() == 2)
    {
      // Clean out any existing content in the button container.
      button_container.innerHTML = '';
        
      // Reset our hidden variation ID field as an invalid product.
      $('variation_id').value = '-2';
        
      // Add a button representing each of our product sizes.
      for (var size_id in variation['sizes'])
      {
        if (size_id == Number(size_id))
        {
          var size_info = variation['sizes'][size_id];
          
          // Create a 'button' link to represent the options.
          button      = document.createElement('a');
          button.href = 'javascript:void(0);';
          button.id   = 'size-' + size_id;
        
          // Measurement in European sizes
          var euro =  '<span class=\'euro\'>';
          euro    += size_info['text'].substr(0, size_info['text'].indexOf(" "));
          euro    += '</span>';
        
          // Measurement in UK sizes
          var uk   =  '<span class=\'uk\'>';
          uk      += size_info['text'].slice(size_info['text'].indexOf("UK ") + 3,
                                        size_info['text'].indexOf(")"));
          uk      += '</span>';
  
          button.innerHTML = euro + uk;
        
          // Disable the button if the size is not in stock.
          if (!size_info['enabled'])
          {
            button.className = 'disabled';
            button.disabled = true;
          }
  
          // Add the button to the button container.
          button_container.appendChild(button);
        }
      }
        
      // Add a clearing DIV tag to the button area, which would have been removed.
      var clear       = document.createElement('div');
      clear.className = 'clear';
      button_container.appendChild(clear);
  
      // Display the main container, in case it was hidden.
      container.style.display = 'block';
    }
    else
    {
      // no second level variations so change hidden variation_id to this colour variation id
      // and remove drop down container
      
      // set hidden field
      $('variation_id').value = this.getItemId(colour_id);
    }
    
    // Display the big image for the selected colour in LuckyZoom.
    zoom.bigImage.src = variation['big_image'];
    zoom.initBigContainer();    
  }


  /**
   * Validates the form data before adding the selected variation to the cart.
   */
  function validateAdd()
  {
    var error        = false;
    var form         = $('add_to_cart');
    var variation_id = form.variation_id.value;
    
    if (this.product.has_variations)
    { 
      // no colour selected
      if (variation_id == -1)
      {
        error = 'Please choose a colour.';
      }
      // no size selected
      else if (variation_id == -2)
      {
        error = 'Please select a size.';
      }
      // out of stock
      else if (variation_id == -3)
      {
        error = 'Sorry, this size is out of stock.';
      } 
    }
    
    if (error !== false)
    {
      alert(error);
      return false;
    }
    else
    {
      return true; 
    } 
  }
}

/**
 * Changes the measurement units used in displaying [shoe] product sizes.
 * Note that this function is outside of the Product 'class'.
 */
function showMeasurementsIn(type)
{
  if ($('size-interface') != null)
  {
    var measure_type = type;
    var m_euro       = $A($('size-interface').getElementsByClassName('euro'));
    var m_uk         = $A($('size-interface').getElementsByClassName('uk'));
    
    switch (measure_type)
    {
      case 'uk':
        setCookie('product_measurement', 'uk');
        $('show_euro').removeClassName('selected');
        $('show_uk').addClassName('selected');
        m_euro.each( function (m) { m.hide(); } );
        m_uk.each( function (m) { m.show(); } );
        break;
      default:
        setCookie('product_measurement', 'euro');
        $('show_uk').removeClassName('selected');
        $('show_euro').addClassName('selected');
        m_uk.each( function (m) { m.hide(); } );
        m_euro.each( function (m) { m.show(); } );
        break;
    }
  }
}


/**
 * Show/Hide tabs
 */

function showTab(tabID){  
  // Reset Tabs Content  
  $$('.switchingtab').each(function(e){
    $(e).className = 'switchingtab hidden';
  });
  
  // Reset Tab Links
  $$('#tab_selector_list li a').each(function(e){
    $(e).className = '';
  });
  
  // Mark Tab Link Selected
  $('tab_select_'+tabID).className = 'selected';
  
  // Show Tab Content
  $('tab_'+tabID).className = 'switchingtab visible';
}

/**
 * Show/Hide tabs for Reviews
 */

function showTab2(tabID){  
  // Reset Tabs Content  
  $$('.switchingtab2').each(function(e){
    $(e).className = 'switchingtab2 hidden';
  });
  
  // Reset Tab Links
  $$('#tab_selector_list2 li a').each(function(e){
    $(e).className = '';
  });
  
  // Mark Tab Link Selected
  $('tab_select_'+tabID).className = 'selected';
  
  // Show Tab Content
  $('tab_'+tabID).className = 'switchingtab2 visible';
}
