<?php if (!defined('HTTP_SERVER')) die('You can not access this file directly!');
/**
  \licence GPL 2005-2010  The osCSS developers - osCSS Open Source E-commerce
  \portion code Copyright (c) 2002 osCommerce
  \package osCSS-2 <www http://www.oscss.org>
  \version 2.1.0
  \date  29/11/10, 11:33
  \author oscim <mail aurelien@oscim.fr> <www http://www.oscim.fr>
  \encode UTF-8
  \file pad_base.php
  \dir includes/classes/
  \page front_attribute_pad_base
  \brief - ATTRIBUTES IN PRODUCT LIST FOR QTPRO -


    Based on prior works released under the GNU General Public License:
      QT Pro prior versions
	Ralph Day, October 2004
	Tom Wojcik aka TomThumb 2004/07/03 based on work by Michael Coffman aka coffman
	FREEZEHELL - 08/11/2003 freezehell@hotmail.com Copyright (c) 2003 IBWO
	Joseph Shain, January 2003
      osCommerce MS2
	Copyright (c) 2003 osCommerce

    \section AA Modifications made:
	 \li 11/2004 - Created
	 \li 12/2004 - Fix _draw_js_stock_array to prevent error when all attribute combinations are
		  out of stock.
	 \li 09/2009  oscim correction xhtml, delete table for list, adaptation oscss
	 \li 09/2010  refonte partiel , re develop code, and delete class enfants

    QT Pro Product Attributes Display Plugin

      pad_base.php - Base Class

      Class Name: pad_base

      This base class, although functional, is not intended to be installed and used
      directly.  It is extended by other classes to provide different display options
      for product attributes on the product information page (product_info.php).
      \section A Methods:
        \li pad_base                            constructor
        \li _SetConfigurationProperties         set local properties from DB config constants
        \li draw                                draw the product attributes
        \li _draw_table_start                   draw start of the table to enclose the attributes display
        \li _draw__attributes         	    draw attributes
        \li _draw_table_end                     draw end of the table to enclose the attributes display
        \li _draw_js_stock_array                draw a Javascript array of in stock attribute combinations
        \li _build_attributes_array             build an array of the attributes for the product
        \li _build_attributes_combinations      build an array of the attribute combinations for the product

      \section B Properties:
        \li products_id                         the product id for attribute display
        \li products_tax_class_id               the products tax class id
        \li show_out_of_stock                   show out of stock attributes flag
        \li mark_out_of_stock                   mark out of stock attributes flag
        \li out_of_stock_msgline                show out of stock message line flag
        \li no_add_out_of_stock                 prevent add to cart of out of stock attributes combinations
*/

/*
 * \class pad_base
 * \brief process calcul attribute for product
*/
class pad_base {
    var $products_id;
    var $products_tax_class_id;
    var $show_out_of_stock;
    var $mark_out_of_stock;
    var $out_of_stock_msgline;
    var $no_add_out_of_stock;


  /**
   * \fn  pad_base($products_id=0, $class_master='')
   * @param $products_id integer  The product id of the product attributes are to be displayed for
   * @param $class_master object , permet de remplacer les appel par defaut de la class, par celle precisé. les methodes doivent être public
   * @returns: nothing
  */
  function pad_base($products_id=0, $class_master='') {
    $this->products_id  = $products_id;
    if ($this->products_id != 0) {
      $product_obj=product::get_item((int)$products_id );
      $this->products_tax_class_id = $product_obj->products_tax_class_id;
      $this->products_original_price = print_products_price_rv($product_obj);
      $this->products_org_price=$product_obj->products_price;
    }
    $this->_SetConfigurationProperties('PRODINFO_ATTRIBUTE_');
    $this->class_master=(is_object($class_master)? $class_master : false );
  }


  /**
   * \fn _SetConfigurationProperties($prefix)
   * \brief Set local configuration properties from osCommerce configuration DB constants
   * @param $prefix string Prefix for the osCommerce DB constants
   * @returns: nothing
  */
  private function _SetConfigurationProperties($prefix) {
    $this->show_out_of_stock    = _cst_bool($prefix . 'SHOW_OUT_OF_STOCK');
    $this->mark_out_of_stock    = tep_cst_define($prefix . 'MARK_OUT_OF_STOCK');
    $this->out_of_stock_msgline = _cst_bool($prefix . 'OUT_OF_STOCK_MSGLINE');
    $this->no_add_out_of_stock  = _cst_bool($prefix . 'NO_ADD_OUT_OF_STOCK');
    $this->actual_price_pull_down  = _cst_bool($prefix . 'ACTUAL_PRICE_PULL_DOWN');
    $this->stock_check  = _cst_bool('STOCK_CHECK');
    $this->up_master=0;
    // compte nbr caractére ligne / max leng / attribut texte
    $this->count_lg_txt=false;
  }


  /**
   * \fn draw_js()
   * \brief   Methode draw des js dans les block header. Necessite d'être appelé en premier
    Prend en charge el chargement prealable à la page, et repartis les scripts
  */
  function draw_js() {
    //load db
    $this->the_attributes = $this->_build_attributes_array(true, true);
    if(count($this->the_attributes)==0)  return;
    //! ecriture en tanpon
    $this->out=$this->_draw_attributes($this->the_attributes);
    //! return js image replace
    $out=$this->_draw_upimage_master($this->the_attributes);
    //! charge pile _image class $page.product
    if($this->count_lg_txt)$out.=$this->_js_draw_textoption();
    //! return js price replace
    if($this->actual_price_pull_down) $out.=$this->_draw_price_master($this->the_attributes);

    return $out;
  }


  /**
   * \fn draw()
   * \brief
    Draws the product attributes.  This is the only method other than the constructor that is
    intended to be called by a user of this class.
    Attributes that stock is tracked for are grouped first and drawn with one dropdown list per
    attribute.  All attributes are drawn even if no stock is available for the attribute and no
    indication is given that the attribute is out of stock.
    Attributes that stock is not tracked for are then drawn with one dropdown list per
    attribute.
    @returns:      string:       HTML for displaying the product attributes
  */
  function draw() {
    $attributes=$this->the_attributes;
    if (sizeof($attributes)==0) return false;
    $out= '<h4>'.TEXT_PRODUCT_OPTIONS.'</h4>'.
	  $this->_draw_table_start().
	  $this->out.
	  $this->_draw_table_end();
    return $out;
  }


  /**
   * \fn _draw_table_start()
   * \brief
    Draws the start of a table to wrap the product attributes display.
    Intended for class internal use only.
    @returns:  string:       HTML for start of table
  */
  private function _draw_table_start() {
    return '<ul class="production_option list">';
  }

  /**
   * \fn _draw_table_end()
   * \brief
    Draws the end of a table to wrap the product attributes display.
    Intended for class internal use only.
    @returns: string:       HTML for end of table
  */
  private function _draw_table_end() {
    return '</ul>';
  }

  /**
   * \fn _draw_attributes($attrib)
   * \brief Boucle pour la mise en html des attribute
   * @param $attrib array tableau attribute
   * @returns: HTML for displaying the product attributes
  */
  private function _draw_attributes($attrib) {
    $out='';
    $o=0;
    $mode_img=array();

    foreach($attrib as $item) {
      //! option non obligatoire
      if($item['omode']==0) $item['default']='';

      //! gestion stock
      $stocked=($item['ostock']==0)? false : true;

      //! boucle adapt sortie
      for ($a=0, $s=sizeof($item['ovals']); $a<$s; $a++) {
	$mode_img[]=$mod=(!empty($item['ovals'][$a]['thumbnail'])? true : false);
	$item['ovals'][$a]['text']=($mod)? tep_image($item['ovals'][$a]['thumbnail'], $item['ovals'][$a]['text']):$item['ovals'][$a]['text'];
	$mode_url[]=(!empty($item['ovals'][$a]['url'])? true : false);
      }

      //! js exe inline
      $js =" onchange=\" ";
//       $js.=(in_array(true,$mode_url)) ? " up_master_image(this.value); " : "";
      $js.=(in_array(true,$mode_url))  ? " up_master_image(".$item['oid'].",this.value); " : "";
      $js.=($this->actual_price_pull_down) ? " up_master_price(".$item['oid'].",this.value); " : "";
      if($stocked) $js.=($this->stock_check && $this->out_of_stock_msgline) ? " stkmsg(this.form);  " : "";
      $js.=" \" ";


      $out.='<li class="product_option_item">'.
	    '<span class="item_heading"><strong>'.$item['oname'].':</strong></span>'.
	    '<span class="item_comment">'.$item['ocomment'].'</span>'.
	    '<span class="item_value">'.$this->_draw_type_att($item, $js).'</span>'.
	    "</li>\n";

      $this->up_master=$o;
      $o++;
    }
    return $out.$this->_draw_out_of_stock_message_js($attrib);
  }


  /**
   * \fn _build_attributes_array($build_stocked, $build_nonstocked)
   * \brief  Build an array of the attributes for the product,
    @date 06.09.2009 12:06:10 oscim add order in sort
    @param
      $build_stocked        boolean   Flag indicating if stocked attributes should be built.
      $build_nonstocked     boolean   Flag indicating if non-stocked attribute should be built.
    @returns:
      array: Array of attributes for the product of the form:
        'oid'       => integer: products_options_id
        'oname'     => string:  products_options_name
        'ovals'     => array:   option values for the option id of the form
                        'id'    => integer:  products_options_values_id
                        'text'  => string:   products_options_values_name
        'default'   => integer: products_options_values_id that the product id
                                contains for this option id and should be the
                                default selection when this attribute is drawn.
                                Set to zero if the product id did not contain
                                this option.
  */
  private function _build_attributes_array($build_stocked, $build_nonstocked) {
    global $languages_id,$currencies,$cart,$page;

    if (!($build_stocked | $build_nonstocked)) return null;

    if ($build_stocked && $build_nonstocked) { $stocked_where=''; }
    elseif (_test_bool($build_stocked)) { $stocked_where="and popt.products_options_track_stock = '1'"; }
    elseif ($build_nonstocked) { $stocked_where="and popt.products_options_track_stock = '0'"; }

    $products_options_name_query = tep_db_query($sql="select distinct popt.products_options_id, popt.products_options_name,popt.products_options_condition, popt.products_options_track_stock, popt.products_options_images_enabled, popt.products_options_type, popt.products_options_length, popt.products_options_comment  from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_ATTRIBUTES . " patrib where patrib.products_id='" . (int)$this->products_id . "' and patrib.options_id = popt.products_options_id and popt.language_id = '" . (int)$languages_id . "' " . $stocked_where . " order by patrib.products_options_sort_order ,popt.products_options_sort_order ASC");

    $attributes=array();
    while ($products_options_name = tep_db_fetch_array($products_options_name_query)) {
      $products_options_array = array();
      $selected='';

      $products_options_query = tep_db_query("select pov.products_options_values_id, pov.products_options_values_name,pov.products_options_values_thumbnail,pa.products_options_values_url, pa.options_values_price, pa.price_prefix from " . TABLE_PRODUCTS_ATTRIBUTES . " pa, " . TABLE_PRODUCTS_OPTIONS_VALUES . " pov where pa.products_id = '" . (int)$this->products_id . "' and pa.options_id = '" . (int)$products_options_name['products_options_id'] . "' and pa.options_values_id = pov.products_options_values_id and pov.language_id = '" . (int)$languages_id . "' order by products_options_sort_order ASC");

      while ($products_options = tep_db_fetch_array($products_options_query)) {
        $products_options_array[] = array('id' => $products_options['products_options_values_id'],
                                          'text' => $products_options['products_options_values_name'],
                                          'url'=> '',
                                          'thumbnail'=> '' );

	/** Option obligatoire */

	/** Image color */
	$products_options_array[sizeof($products_options_array)-1]['thumbnail']=@$products_options['products_options_values_thumbnail'];

	/** url /option value  */
        if (_test_bool($products_options_name['products_options_images_enabled'])){
          $products_options_array[sizeof($products_options_array)-1]['url']=$products_options['products_options_values_url'];
	  if(!in_array($products_options['products_options_values_url'] ,$page->product->pile_img)) $page->product->pile_img[]=$products_options['products_options_values_url'];
        }
	/** Price / option value */
        if ($products_options['options_values_price'] != '0') {
          $products_options_array[sizeof($products_options_array)-1]['text'] .= ' (' . $products_options['price_prefix'] . $currencies->display_price($products_options['options_values_price'], tep_get_tax_rate($this->products_tax_class_id)) .')';
        }
	/** */
        if($this->actual_price_pull_down){
        //Option prices will displayed as a final product price. This can (currently) only be used with a satisfying result if you have only one option per product.

	  // in case price lowers, don't add values, subtract.
	  // force float (in case) using the 0.0;
          if ($products_options['price_prefix'] == '-')  $show_price = 0.0 + $this->products_original_price - $products_options['options_values_price'];
          else  $show_price = 0.0 + $this->products_original_price + $products_options['options_values_price'];

//           $products_options_array[sizeof($products_options_array)-1]['text'] .= '&nbsp;'.$currencies->display_price( $show_price, tep_get_tax_rate($this->products_tax_class_id)).' ';
// 	  $products_options_array[sizeof($products_options_array)-1]['text'] .= ' (' . $products_options['price_prefix'] . $currencies->display_price($products_options['options_values_price'], tep_get_tax_rate($this->products_tax_class_id)) .')';
	  $products_options_array[sizeof($products_options_array)-1]['price'] =$currencies->display_price( $show_price, tep_get_tax_rate($this->products_tax_class_id));
	  $products_options_array[sizeof($products_options_array)-1]['prefix'] =$products_options['price_prefix'];
	  $products_options_array[sizeof($products_options_array)-1]['adjust'] =$products_options['options_values_price'];

        }else{ //Display the option prices as differece prices with +/- prefix as usually
          if ($products_options['options_values_price'] != '0') {
	    $products_options_array[sizeof($products_options_array)-1]['price'] = $this->products_original_price;
	    $products_options_array[sizeof($products_options_array)-1]['prefix'] ='';
          }
        }

	$products_options_array[sizeof($products_options_array)-1]['original_price'] = $this->products_org_price;

	if(empty($selected))$selected=$products_options['products_options_values_id'];
      }
      if (isset($cart->contents[$this->products_id]['attributes'][$products_options_name['products_options_id']])) $selected = $cart->contents[$this->products_id]['attributes'][$products_options_name['products_options_id']];


      /** Active compte caractére */
      $this->count_lg_txt=($products_options_name['products_options_type']==1)? true : false;

      $attributes[]=array('oid'=>$products_options_name['products_options_id'],
                          'oname'=>$products_options_name['products_options_name'],
			  'ostock'=>$products_options_name['products_options_track_stock'],
			  'omode'=>$products_options_name['products_options_condition'],
                          'oimages'=>$products_options_name['products_options_images_enabled'],
			  'otype'=>$products_options_name['products_options_type'],
                          'olength'=>$products_options_name['products_options_length'],
                          'ocomment'=>$products_options_name['products_options_comment'],
                          'ovals'=>$products_options_array,
                          'default'=>$selected);
    }
    return $attributes;
  }

  /**
   * \fn _draw_type_att($array,$js)
   * \brief Construction du selecteur d'attribut en fonction du type d'attribut
    @param
     $array array
     $js  string
  */
  private function _draw_type_att($array,$js){
    $field ='';

    //! utilise la function de la class appelante, en rempacement de celle ci
    if($this->class_master !=false && method_exists($this->class_master, '_draw_type_att') )   return $this->class_master->_draw_type_att($array,$js);


    $selected=(tep_not_null($array['default']))? $array['default'] : '';
    switch ($array['otype']) {
      case '2': // Text
	$field .= '<label> '.$array['ovals'][0]['text'].'</label>'.tep_draw_hidden_field('Valueid['  .$array['oid'].']',$array['ovals'][0]['id'])
		.tep_draw_input_field('id[' .TEXT_PREFIX.$array['oid'].']', 'id_' .TEXT_PREFIX .$array['oid'].'','', ' maxlength="'.$array['olength'].'" onkeydown="textCounter(this,\'progressbar' . $array['oid'] . '\',' . $array['olength'] . ')" onkeyup="textCounter(this,\'progressbar' . $array['oid'] . '\',' . $array['olength'] . ')" onfocus="textCounter(this,\'progressbar' .$array['oid'] . '\',' . $array['olength'] . ')"')
		.'<div id="progressbar' . $array['oid'] . '" class="progress"></div>';
      break;
      case '5': //File
      break;
      case '3'://Radio
	$field .= tep_draw_pull_down_radio('id['.$array['oid'].']','id_'.$array['oid'],$array['ovals'],$selected,$js);
      break;
      case '4': //Checkbox
	$field .= tep_draw_pull_down_checkbox('id['.$array['oid'].']','id_'.$array['oid'],$array['ovals'],$selected,$js);
      break;
      case '1': // Select
      default:
	$field .= tep_draw_pull_down_menu('id['.$array['oid'].']','id_'.$array['oid'],$array['ovals'],$selected, $js);
    }
    return $field;
  }


  /**
   * \fn _build_attributes_combinations($attributes, $showoos, $markoos, &$combinations, &$selected_combination, $oidindex=0, $comb=array(), $id="", $text='', $isselected=true)
   * \brief A recursive method for building an array enumerating the attribute combinations for the product
    @param
      $attributes             array     An array of the attributes that combinations will be built for.
                                        Format is as returned by _build_attributes_array.
      $showoos                boolean   Flag indicating if non-stocked attributes should be built.
      $markoos                string    'Left' if out of stock indication is to be appended in front of the
                                        attribute combination text.  'Right' if out of stock indication is
                                        to be appended at the end of the attribute combination text.
      $combinations           array     Array of the attribute combinations is returned in this parameter.
                                        Should be set to an empty array before an external call to this method.
                                          'comb'        => array:   array of a single attribute combination
                                                                      options_id => options_value_id
                                          'id'          => string:  options/values string for this
                                                                    combination in the form for the
                                                                    key of the products_stock table
                                                                      opt_id-val_id,opt_id-val_id,...
                                          'text'        => string:  Text for this combination.  Values text
                                                                    is as built by _build_attributes_array
                                                                     and contains the add/subtract price for
                                                                     the option value if applicable.  Form is:
                                                                       values_text, values_text
      $selected_combination   integer   Index into the $combinations array of the combination that should
                                        be the default selection when the combination is drawn is returned in
                                        this parameter.  Determined from product id.  Should be set to zero
                                        before an external call to this method.

    @param  for internal recursion use only:
      $oidindex               integer   Index into the $attributes array of the option to operate on.
      $comb                   array     Array containing option id/values of combination built so far
                                          products_options_id => products_options_value_id
      $id                     string    Contains string of options/values built so far
      $text                   string    Text for the options values constructed so far.
      $isselected             boolean   Flag indicating if so far all option values in this combination
                                        were indicated to be defaults in the product id.
    @returns:
      see $combinations and $selected_combination parameters above
      no actual function return value.
  */
  private function _build_attributes_combinations($attributes, $showoos, $markoos, &$combinations, &$selected_combination, $oidindex=0, $comb=array(), $id="", $text='', $isselected=true) {
    global $cart;

    foreach ($attributes[$oidindex]['ovals'] as $attrib) {
      $newcomb = $comb;
      $newcomb[$attributes[$oidindex]['oid']] = $attrib['id'];
      $newid=$id.','.$attributes[$oidindex]['oid'].'-'.$attrib['id'];
      $newtext = $text.", ".$attrib['text'];
//       if (isset($cart->contents[$this->products_id]['attributes'][$attributes[$oidindex]['oid']]))
//         $newisselected = ($cart->contents[$this->products_id]['attributes'][$attributes[$oidindex]['oid']] == $attrib['id']) ? $isselected : false;
//       else
        $newisselected = false;
      if (isset($attributes[$oidindex+1])) {
        $this->_build_attributes_combinations($attributes, $showoos, $markoos, $combinations, $selected_combination, $oidindex+1, $newcomb, $newid, $newtext, $newisselected);
      }
      else {
        $is_out_of_stock=product::get_products_stock(tep_get_prid($this->products_id),$newcomb);

        if (/*$is_out_of_stock<=0 && */$showoos == true) {
          switch ($markoos) {
            case 'Left':   $newtext=( ($is_out_of_stock<=0) ? TEXT_OUT_OF_STOCK.' - ' : '').substr($newtext,2);
            break;
            case 'Right':  $newtext=substr($newtext,2).(($is_out_of_stock<=0)  ? ' - '.TEXT_OUT_OF_STOCK : '');
            break;
            default:       $newtext=substr($newtext,2);
          }
          $combinations[] = array('comb'=>$newcomb, 'id'=>substr($newid,1), 'text'=>$newtext, 'stock' =>$is_out_of_stock);
          if ($newisselected) $selected_combination = sizeof($combinations)-1;
        }
      }
    }
  }


  /**
   * \fn _draw_js_stock_array($combinations)
   * \brief Draw a Javascript array containing the given attribute combinations.
      Generally used to draw array of in-stock combinations for Javascript out of stock
      validation and messaging.
      @param
        $combinations        array   Array of combinations to build the Javascript array for.
                                    Array must be of the form returned by _build_attributes_combinations
                                    Usually this array only contains in-stock combinations.
      @returns:
        string:                 Javacript array definition.  Excludes the "var xxx=" and terminating ";".  Form is:
                                {optval1:{optval2:{optval3:1,optval3:1}, optval2:{optval3:1}}, optval1:{optval2:{optval3:1}}}
                                For example if there are 3 options and the instock value combinations are:
                                  opt1   opt2   opt3
                                    1      5      4
                                    1      5      8
                                    1     10      4
                                    3      5      8
                                The string returned would be
                                  {1:{5:{4:1,8:1}, 10:{4:1}}, 3:{5:{8:1}}}
  */
  private function _draw_js_stock_array($combinations) {
// print_r($combinations);
    if (!((isset($combinations)) && (is_array($combinations)) && (sizeof($combinations) > 0))){
      return '{}';
    }
    $out='';
    foreach ($combinations[0]['comb'] as $oid=>$ovid) {
      $out.='{'.$ovid.':';
      $opts[]=$oid;
    }
    $out.=$combinations[0]['stock'];

    for ($combindex=1; $combindex<sizeof($combinations); $combindex++) {
      $comb=$combinations[$combindex]['comb'];
      for ($i=0; $i<sizeof($opts)-1; $i++) {
        if ($comb[$opts[$i]]!=$combinations[$combindex-1]['comb'][$opts[$i]]) break;
      }
      $out.=str_repeat('}',sizeof($opts)-1-$i).',';
      if ($i<sizeof($opts)-1) {
        for ($j=$i; $j<sizeof($opts)-1; $j++)
          $out.=$comb[$opts[$j]].':{';
      }
      $out.=$comb[$opts[sizeof($opts)-1]].':'. (($combinations[$combindex]['stock']>0) ? $combinations[$combindex]['stock']: 0);
    }
    $out.=str_repeat('}',sizeof($opts));

    return $out;
  }


  /**
   * \fn _draw_out_of_stock_message_js($attributes)
   * \brief
    draw Javascript to display out of stock message for out of stock attribute combinations
    @param array $attributes        Array of attributes for the product.  Format is as returned by
                              _build_attributes_array.
    @returns: string:         Javascript to display out of stock message for out of stock attribute combinations
  */
  function _draw_out_of_stock_message_js($attributes) {
    $out='';

    $out.="<li><span id=\"oosmsg\" class=errorBox></span>\n";
// print_r($attributes);

    if (($this->out_of_stock_msgline | $this->no_add_out_of_stock)) {

      $combinations = array();
      $selected_combination = 0;
      $this->_build_attributes_combinations($attributes, $this->show_out_of_stock, 'None', $combinations, $selected_combination);

      $out.="<script type=\"text/javascript\"><!--\n";
      $out.="  function check_test(input) {\n \n  ";
      $out.="   if(input.type =='select-one'){  ";
      $out.="    var selected_value = input.selectedIndex;  \n  ";
      $out.="    return input[selected_value].value;  \n  ";
      $out.="   } else {  \n  ";
      $out.="     for (var i=0; i<input.length;i++) { \n";
      $out.="       if (input[i].checked || input[selected_value]) return input[i].value;  \n";
      $out.="     } \n";
      $out.="    } \n";
      $out.="   } \n";
      $out.="  function chkstk(frm) {\n";

      // build javascript array of in stock combinations
      $out.="    var stk=".$this->_draw_js_stock_array($combinations).";\n";
      $out.="    var instk=false;\n";
      $out.="    if(frm ==null)  return ''; \n";

      // build javascript if statement to test level by level for existance
      $out.=' var qty = document.getElementById("products_quantity").value ;   ';
	for ($i=0; $i<sizeof($attributes); $i++) {
	  $out.=' var input'.$i." = frm.elements['id[".$attributes[$i]['oid']."]']; \n";
	  $out.=" var val".$i." =check_test(input".$i."); ";
	}
      $out.="\n".'if( stk';
	for ($i=0; $i<sizeof($attributes); $i++) {
	  $out.="[val".$i."]";
	}
      $out.=' >=  qty ) return true; '."\n";
      $out.='else return false;';
      $out.="  }\n";



      if ($this->out_of_stock_msgline) {
        // set/reset out of stock message based on selection
        $out.="  function stkmsg(frm) {\n";
        $out.="    var instk=chkstk(frm);\n";
        $out.="    var span=document.getElementById(\"oosmsg\");\n";
        $out.="    while (span.childNodes[0])\n";
        $out.="      span.removeChild(span.childNodes[0]);\n";
        $out.="    if (!instk)\n";
        $out.="      span.appendChild(document.createTextNode(\"".addslashes(TEXT_OUT_OF_STOCK_MESSAGE)."\"));\n";
        $out.="    else\n";
        $out.="      span.appendChild(document.createTextNode(\" \"));\n";
        $out.="  }\n";
        //initialize out of stock message
//         $out.="  stkmsg(document.forms.cart_quantity);\n";
      }

      if ($this->no_add_out_of_stock) {
        // js to not allow add to cart if selection is out of stock
        $out.="  function chksel() {\n";
        $out.="    var instk=chkstk(document.forms.cart_quantity);\n";
        $out.="    if (!instk) alert('".TEXT_OUT_OF_STOCK_MESSAGE."');\n";
        $out.="    return instk;\n";
        $out.="  }\n";
//         $out.="  document.id_" . (int)$this->products_id . ".onsubmit=chksel;\n";
        $out.="  document.forms.cart_quantity.onsubmit=chksel;\n";
      }
      $out.="//--></script>\n";
    }
    $out.="</li>\n";
    return $out;
  }

  /**
   * \fn
   * \brief Remplacement de l'image principale du produits
   * @param $attributes array
  */
  private function _draw_upimage_master($attributes) {
    $i=$this->up_master;
    $out="<script type=\"text/javascript\"><!--\n";
    $out.="function up_master_image(idn,id_value){\n";
    $tableau_JS="Tableau";
    $out.= sprintf("%s = new Array();\n",$tableau_JS);
        foreach($attributes[$i]['ovals'] as $keyItems => $valueItems) {
          foreach($valueItems as $keyItem => $valueItem) {
            if($keyItem=='id') $id=$valueItem;
	    elseif($keyItem=='url')
		$out.=  sprintf("%s[%s] = %s;\n",$tableau_JS, $id,
                     ( is_string($valueItem)||empty($valueItem) ) ?  "\"".addslashes($valueItem)."\"" : $valueItem);
          }
        }
    $out.=" change_image_master('".HTTP_SERVER.DIR_WS_CATALOG.DIR_WS_IMAGES."'+".$tableau_JS."[id_value]) ;\n ";
    $out.="}\n";
    $out.="//--></script>\n";
    return $out;
  }

  /**
   * \fn _draw_price_master($attributes)
   * \brief Remplacement de l'image principale du produits
   * @param $attributes array
  */
  private function _draw_price_master($attributes) {
    global $osCSS_Cache;
    $i=$this->up_master;
    if ($osCSS_Cache->read('_draw_price_master-'.$this->products_id.'-ctr_js', 60) ) {
      $out = $osCSS_Cache->getCache();
    } else {
    $out="<script type=\"text/javascript\"><!--\n";

    $out.="function up_master_price(idn,id_value){\n";
    $out.=" var master2 =  document.getElementById('price_master');\n";
    $tableau_JS="Tableau2";
    $out.= sprintf("%s = new Array();\n",$tableau_JS);
      for($i=0, $m=count($attributes); $i< $m; $i++){
	$out.=  sprintf("%s[%s]= new Array();\n",$tableau_JS, $i);
        foreach($attributes[$i]['ovals'] as $keyItems => $valueItems) {
          $out.=  sprintf("%s[%s][%s]= new Array();\n",$tableau_JS,$i, $keyItems);
          foreach($valueItems as $keyItem => $valueItem) {
            $out.=  sprintf("%s[%s][%s]['%s'] =%s;\n",$tableau_JS, $i, $keyItems, $keyItem,
                     ( is_string($valueItem)||empty($valueItem) ) ?  "\"".addslashes($valueItem)."\"" : $valueItem);
          }
        }
      }
//     $out.=" var pile_price = parseFloat(".$tableau_JS."[idn][i]['adjust']);\n";
//     $out.=" var pile_prefix=".$tableau_JS."[idn][i]['prefix'] ;\n";
    $out.="  idn= (idn-1) ;\n";
    $out.="  tab = ".$tableau_JS."[idn] ;\n";
    $out.=" var actuel = parseFloat(master2.innerHTML) ;\n";
//     $out.="   if ( pile_price != actuel ){;\n";
//     $out.="	if(pile_prefix == '-' )  actuel = parseFloat(master2.innerHTML)+ parseFloat(pile_price) ;\n";
//     $out.="	else actuel = parseFloat(master2.innerHTML)-parseFloat(pile_price) ;\n";
//     $out.="   }else actuel = parseFloat(master2.innerHTML);\n";
    $out.="  actuel = parseFloat(master2.innerHTML);\n";
    $out.=" for(i=0; i<tab.length; i++) { \n
	      if(i==0)actuel = parseFloat(".$tableau_JS."[idn][i]['original_price']) ; \n
              if(".$tableau_JS."[idn][i]['id']==id_value ){\n
		if(".$tableau_JS."[idn][i]['prefix'] == '+' ) master2.innerHTML=actuel+  parseFloat(".$tableau_JS."[idn][i]['adjust']) ;\n
		else master2.innerHTML= actuel -  ".$tableau_JS."[idn][i]['adjust'] ;\n
		pile_price = ".$tableau_JS."[idn][i]['adjust'] ;\n
		pile_prefix = ".$tableau_JS."[idn][i]['prefix'] ;\n
	      }\n
            } \n";
    $out.="}\n";
    $out.="//--></script>\n";

      $osCSS_Cache->writeBuffer($out);
    }

    return $out;
  }



  /**
   * \fn _js_draw_textoption()
   * \brief Calcul nombre caratere restant / specifique option text champs dipso pour user
  */
  private function _js_draw_textoption(){
    global $osCSS_Cache;
    if ($osCSS_Cache->read('__js_draw_textoption-'.$this->products_id.'-ctr_js', 60) ) {
      $out = $osCSS_Cache->getCache();
    } else {

    $out ="<script language=\"javascript\"><!--\n";
    $out.=" // BOF Product Type Feature\n";
    $out.=" function textCounter(field,counter,maxlimit,linecounter) {\n";
	$out.="     // text width//\n";
	$out.="     var fieldWidth =  parseInt(field.offsetWidth);\n";
	$out.="     var charcnt = field.value.length;\n";
	$out.="     // trim the extra text\n";
	$out.="     if (charcnt > maxlimit) {\n";
	$out.=" 	    field.value = field.value.substring(0, maxlimit);\n";
	$out.="     } else {\n";
	$out.="     // progress bar percentage\n";
	$out.="     var percentage = parseInt(100 - (( maxlimit - charcnt) * 100)/maxlimit) ;\n";
	$out.="     document.getElementById(counter).style.width =  parseInt((fieldWidth*percentage)/100)+\"px\";\n";
	$out.="     document.getElementById(counter).innerHTML=\"Limit: \"+percentage+\"%\"\n";
	$out.="     // color correction on style from CCFFF -> CC0000\n";
	$out.="     setcolor(document.getElementById(counter),percentage,\"background-color\");\n";
	$out.="     }\n";
    $out.=" }\n";
    $out.=" function setcolor(obj,percentage,prop){\n";
	$out.="     obj.style[prop] = \"rgb(80%,\"+(100-percentage)+\"%,\"+(100-percentage)+\"%)\";\n";
    $out.=" }\n";
    $out.=" // EOF Product Type Feature\n";
    $out.=" //-->\n";
    $out.="</script>\n";

      $osCSS_Cache->writeBuffer($out);
    }

    return $out;
  }
}
?>