/*
var base_ref = 'http://www.example.com';
var images = new Array();
var tmp_images = new Array();
tmp_images[0] = 'image1.jpg';
tmp_images[1] = 'image2.jpg';
tmp_images[2] = 'image3.jpg';
tmp_images[3] = 'image4.jpg';
tmp_images[4] = 'image5.jpg';

function cache_images () {
  for (var i=0; i < tmp_images.length; i++){
    var cacheimage=new Image();
    var tmp_name = tmp_images[i];
    var url = tmp_images[i] + '.png';
    cacheimage.src=url;
    images[tmp_name]=cacheimage;
  }
}


// глобальное хранилище
var GlobalScope = {
   // example
   Property: 'test'
  ,Property1: function(){
    //alert("GlobalScope.Property1 init");
    return {
       subProp1: 'test'
      ,subProp2: 'test'
    }
  }()
  ,Method: function(){
    alert("GlobalScope.Method()");
    return {
       prop1: 'test'
      ,prop2: 'test'
    }
  }
}

/**/

//###### SYS
function getOffsetRect(elem) {
    // (1)
    var box = elem.getBoundingClientRect()

    // (2)
    var body = document.body
    var docElem = document.documentElement

    // (3)
    var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop
    var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft

    // (4)
    var clientTop = docElem.clientTop || body.clientTop || 0
    var clientLeft = docElem.clientLeft || body.clientLeft || 0

    // (5)
    var top  = box.top +  scrollTop - clientTop
    var left = box.left + scrollLeft - clientLeft

    return { top: Math.round(top), left: Math.round(left) }
}


/**
 * позиционирование элемента
 *
 * mEl - обьект или его id
 * sTypes - c,t,b,l,r,lt,lb,rt,rb
 * iXOff - конечное смещение по X
 * iYOff - конечное смещение по Y
 */
function ElPos( mEl, sTypes, iXOff, iYOff )
{
	if ("object" != typeof(mEl) && !(mEl = $(mEl)) )
    return;

  var x, y, l;

  if(!iXOff)
    iXOff = 0
  if(!iYOff)
    iYOff = 0

  // centering element
  x = (document.documentElement.clientWidth-mEl.getWidth())/2
  y = (document.documentElement.clientHeight-mEl.getHeight())/2
  sTypes = sTypes.substr(0, 2)
  l = sTypes.length

  for (var i=0; i<l; i++) {
    switch (sTypes.substr(i, 1)) {
       case 'c':
         break;
       case 't':
           y = y-y
         break;
       case 'b':
           y = y+y
         break;
       case 'l':
           x = x-x
         break;
       case 'r':
           x = x+x
         break;
    }
  }

  mEl.style.left = x+iXOff+document.viewport.getScrollOffsets().left+"px"
  mEl.style.top  = y+iYOff+document.viewport.getScrollOffsets().top+"px"

/*
  alert($H({
     x:x
    ,y:y
    ,scrlLet:document.viewport.getScrollOffsets().left
    ,scrlTop:document.viewport.getScrollOffsets().top
    ,eLeft:mEl.style.left
    ,eTop:mEl.style.top
//,iXOff:iXOff
//,iYOff:iYOff
  }).inspect());

/*
  // debug
  <div id=test style='border:50px solid #000; width:100px; height:100px; position:absolute'></div>
  <script>ElPos( 'test' ,'r', -100 )</script>
*/
}

/**
 * Функция "блокирует" указанный mEl, накрывая его слоем с прозрачностью.
 *
 * mEl - строка id через зяпятую или массив с id элементов
 *
 * @todo
 * возвращаемый disabler сделать обьектом, а не массивом
 * посмотреть используется ли где возвращенный результат от Disabler,
 * если нет то удалить это вообще
 *
 * bEnable - переименовать в bOff или подругому,
 * мысль в том чтобы выключать действие выключателя
 * Disabler(mEl) - блокировать элемент; Disabler(mEl, false) - отменить блокировку
 */
function Disabler(mEl)
{
  if ("array" != typeof(mEl))
    mEl = new Array(mEl);

  for(var i=0, l=mEl.length; i<l; i++) {

    var oEl = $(mEl[i]);

    if (!oEl) {
      alert("Disabler: not found Element ["+oEl+"]")
      continue;
    }

    var top = getOffsetRect(oEl).top+"px";
    var left =getOffsetRect(oEl).left+"px";

    var disabler = {}

    disabler.mask = new Element('DIV').setStyle({
       zIndex:"1000"
      ,position:"absolute"
      ,left:left
      ,top:top
      ,width:oEl.getWidth()+"px"
      ,height:oEl.getHeight()+"px"
    })

    disabler.image = disabler.mask.cloneNode(true)

    disabler.mask.setStyle({
       left:left
      ,top:top

      // Editable
      ,backgroundColor:"#E0E0E0"
      ,opacity:.75
      ,filter:"alpha(opacity:75)"
    })

    disabler.image.setStyle({
       zIndex:"1001"
      ,backgroundRepeat:"no-repeat"

      // Editable
      ,backgroundImage:"url(./tpl/def/loader.gif)"
      ,backgroundPosition:"left"
    })

    document.body.appendChild(disabler.mask)
    document.body.appendChild(disabler.image)

    disabler.remove = function() {
      this.mask.remove()
      this.image.remove()
    }

    return disabler;
  }
}

/**
 * возвращает текущий или переданный Location,
 * с примененным фильтром по переменным
 *
 * @param string sVarsFilter имена переменных через запятую
 * @param bool bFilterInverse переданные переменные вырезать
 * @return string
 */
function Location(sVarsFilter, bFilterInverse, sLocation )
{
  var i3=0, iIndexEqual, aAllowVars = new Array()

  if (!sLocation)
    sLocation = window.location.toString()

  var iIndexQuery = sLocation.indexOf('?')
  if (-1 == iIndexQuery)
    return sLocation+"?"

  var sLocationAdress = sLocation.substr(0, iIndexQuery+1)
  var aQueryVars = sLocation.substr(iIndexQuery+1).split('&')

  var aVars = sVarsFilter.split(",");
  for (var i=0, l=aQueryVars.length; i<l; i++) {
    if((iIndexEqual = aQueryVars[i].indexOf('=')) && -1 != iIndexEqual)
      var sQueryVarName = aQueryVars[i].substr(0, iIndexEqual)
    else
      var sQueryVarName = aQueryVars[i]

    var bVarFind = false
    for (var i2=0, l2=aVars.length; i2<l2; i2++) {
      if (aVars[i2]==sQueryVarName)
        bVarFind = true
    }
    // 0110^1010 = 1100 XOR
    if (bFilterInverse^bVarFind) {
      aAllowVars[i3] = aQueryVars[i]
      i3++
    }
  }

  return sLocationAdress+aAllowVars.join('&');
}


/**
 * Класс работы с куками
 *
 * @type Cookie
 */
var Cookie = {

  store : (function(){
    var allCookies = document.cookie.split ('; ');
    var values = new Array();
    for (var i=0, l=allCookies.length; i<l; i++) {
      var cookiesPair = allCookies[i].split('=');
      values[cookiesPair[0]] = unescape(cookiesPair[1]);
    }
    return values
  })(),

  set : function(name,value,days) {
    if (days) {
      var date= new Date();
      date.setTime(date.getTime()+(days*24*60*60*1000));
      var expires = date.toGMTString();
    }
    else {
      var date= new Date();
      date.setTime(date.getTime()+(365*24*60*60*1000));//default to 1 year
      var expires = date.toGMTString();
    }
    document.cookie = name+"="+escape (value )+"; expires="+expires+";path=/";
  },

  get : function(name) {
    return this.store[name];
  },

  unset : function(name) {
    this.create(name,"",-1);
    this.store[name]=null;
  }
}

//###### 


//###### REFACTOR

/**
 * Сортировка
 * @param {} sField
 */
function setOrder(sField)
{
  // если поле не выбрано
  var sURL = window.location.toString()
  var sParam = ""
  if (-1 == sURL.search('\\bsrtf='+sField+'\\b')){
    sURL = Location("srtf,srtr,p", true)
    sParam = "&srtf="+sField
  }
  else {
    if (-1 == sURL.search("\\bsrtr\\b") )
      sParam = '&srtr';
    else
      sURL = Location("srtr,p", true)
  }
  window.location.href = sURL+sParam;
}

function setFirm(iIdFirm)
{
  window.location.href = Location("f,p", true)+"&f="+iIdFirm;
}

function unsetFirm()
{
  window.location = Location("f,p", true)
}

function setSearch()
{
  //var sURL = LocationWithoutVars("r,u,ss,pss,p,srtf,srtr")+"&"+Form.serialize('search')
  var sURL = Location("f")+"&"+Form.serialize('search')
  //document.write(sURL) //debug
  window.location.href = sURL;
}
//###### 



//###### EXTERNAL ORDER

/**
 * External PopUp
 */
var oExtPopUp = {

   // должна быть глобальной
   win:{}

   // url for external service
  ,url:''

  ,Order: function (id, name, price, priceDsc, priceRetail, priceRetailDsc) {
    var params = {
       i:id
      ,n:name
      ,p1:price
      ,pd1:priceDsc
      ,p2:priceRetail
      ,pd2:priceRetailDsc
      ,psi:Cookie.get('PHPSESSID')
    }

    var props = new Array(
       'width=272'
      ,'height=590'
      ,'left='+(document.documentElement.clientWidth-(265+160))
      ,'top=250'
      ,'resizable=1'
    )
    this._Open('order', props, params );

    return false; // for tag <a>
  }

  ,Basket: function () {

    var params = {
      psi:Cookie.get('PHPSESSID')
    }

    var props = new Array(
       'width=720'
      ,'height=400'
      ,'left='+(document.documentElement.clientWidth/2-360)
      ,'top=250'
      ,'resizable=1'
      ,'scrollbars=1'
    )
    this._Open('basket', props, params );

    return false; // for tag <a>
  }

  ,_Open: function (id, props, params) {

    this.win = window.open('', id, props.join(','))

    // всегда принудительный replace
    // из-за различного поведения window.open в браузерах
    this.win.location.replace('about:blank')

    if (Prototype.Browser.IE)
      this._ChangeContent($H(params).toQueryString())
    else
      window.setTimeout ('oExtPopUp._ChangeContent("'+$H(params).toQueryString()+'")', 100)
  }

  /**
   * "статический" метод
   *
   */
  ,_ChangeContent: function (params) {
    // flash вместо gif, т.к. gif останавливает анимацию при смене location
    oExtPopUp.win.document.write('<embed height="100%" width="100%" wmode="transparent" quality="best" src="tpl/def/loader.swf" type="application/x-shockwave-flash" />')
    oExtPopUp.win.location.replace(oExtPopUp.url+'?'+params);
    oExtPopUp.win.focus();
  }
}

/*
var form = document.createElement("form");
form.setAttribute("method", "post");
form.setAttribute("action", "test.jsp");

// setting form target to a window named 'formresult'
form.setAttribute("target", "formresult");

var hiddenField = document.createElement("input");
hiddenField.setAttribute("name", "id");
hiddenField.setAttribute("value", "bob");
form.appendChild(hiddenField);
document.body.appendChild(form);

window.open('test.html', 'formresult', 'scrollbars=no,menubar=no,height=600,width=800,resizable=yes,toolbar=no,status=no');

form.submit();
*/
//###### 


//###### GATE 

/**
 *
 * @param {} options
 * {
 *    url:''
 *   ,params:{}
 *   ,onSuccess:function(info, oData){}
 *   ,onFailure:function(info, oData){}
 *   ,loaderTarget:el
 * }
 *
 * @param {} scope
 *
 */
function Gate(options, scope) {
  // ini options
  options.url = options.url || "/"
  options.params = options.params || {}
  options.onSuccess = options.onSuccess || function(){}
  options.onFailure = options.onFailure || function(){}
  
  var loader = options.loaderTarget 
    ? Disabler(options.loaderTarget) 
    : false
  ;

  scope = scope || this
    
  new Ajax.Request (options.url, {
     method:'post'
    ,parameters:options.params
    ,evalJSON:'force'
    ,onSuccess:function(result){

      // ini
      var success, info, data, handler;

      if (null != result.responseJSON){
        success = (result.responseJSON.success != undefined ? result.responseJSON.success : false)
        info = (result.responseJSON.info != undefined ? result.responseJSON.info : "")
        data = (result.responseJSON.data != undefined ? result.responseJSON.data : {})
      }
      else {
        success = false
        info = ""
        data = {}
      }

      if (success)
        handler = options.onSuccess
      else
        handler = options.onFailure

      handler.call(scope, info, data)

    }

    ,onFailure:function(result) {
      alert('Gate: onFailure')
    }

    // Not guaranteed
    ,onLoaded:function(result) {
      if (loader)
        loader.remove();
    }
  });
}
//######

//###### WINDOWS

var BaseWindow = Class.create({

   window:undefined
  ,controller:undefined

  /**
   * текущий dom эл. формы заказа 
   * @type {Boolean}
   */
  ,curForm:undefined

  ,initialize: function(clr) {
    this.controller = clr;
  }
  
  ,Init : function () {
    //this.controller = {} ;    
  }
  
  ,Show : function () {
  }

  ,Hide : function () {
    this.window.close();
  }
  
  ,bindForm : function(id) {
    this.curForm = $(id);
  }
  
  /**
   * Сброс формы 
   * - очистка примечания 
   * - перегрузка капчи 
   */
  ,Reset : function() {
    this.curForm.select('[name=note]')[0].value="";
    this.ReloadCaptcha(true);
  }
  
  /**
   * Перезгрузка капчи
   *
   * @param boolean bForced
   */
  ,ReloadCaptcha : function (bForced) {

    if (bForced || !this.curForm.select('img.captcha')[0].src) {
      // рандом для выключения кэширования
      this.curForm.select('img.captcha')[0].src=this.controller.urlCaptcha+"&"+Math.random();
      this.curForm.select('[name=captcha]')[0].value="";
    }
  }
});

var BaseOrderWindow = Class.create(BaseWindow, {
  
  /**
   * Генерирует и заполняет HTML области
   * в форме заказа данными о товаре
   *
   * @param {String} id
   * @param {String} name
   * @param {String} price
   * @param {String} priceDsc
   * @param {String} priceRetail
   * @param {String} priceRetailDsc
   * @param {String} formId
   */
  setFormData : function(id, name, price, priceDsc, priceRetail, priceRetailDsc, formId) {

    this.controller.ResetStore();
    this.controller.toOrder( new OrderUnit(id) )

    this.bindForm(formId);
    this.ReloadCaptcha(true);

    // set order data
    this.curForm.select('[class=o_name]')[0].innerHTML = name;
    this.curForm.select('[class=o_price]')[0].innerHTML = this.sPriceBlock(
       price
      ,priceDsc
      ,priceRetail
      ,priceRetailDsc
    );
  }

  /**
   * возвращает HTML блок с ценами товара
   * для формы заказа в списке товаров и странице товара
   *
   * @param {String} price
   * @param {String} priceDsc
   * @param {String} priceRetail
   * @param {String} priceRetailDsc
   * @return {String}
   */
  ,sPriceBlock: function (price, priceDsc, priceRetail, priceRetailDsc)
  {
    // TypePrice   sCheckedPrice
    var sTP, sTPR, sCP, sCPR;

    sTP = sTPR = 'hidden';
    sCP = sCPR = '';

    if (
      (!price.blank() || !priceDsc.blank())
      &&
      (!priceRetail.blank() || !priceRetailDsc.blank())
    )
      sTP = sTPR = 'radio';

    if (price)
      sCP = 'checked'
    else if (priceRetail && !price)
      sCPR = 'checked'

    return this.sPriceHtml(sTP, sCP, 1, 'Оптовая', price, priceDsc)
      + this.sPriceHtml(sTPR, sCPR, 2, 'Розничная', priceRetail, priceRetailDsc);
  }

  /**
   * Генерирует HTML для цены товара
   * для формы заказа в списке товаров и странице товара
   *
   * @param {String} price
   * @param {String} priceDsc
   * @param {String} priceRetail
   * @param {String} priceDsc
   * @return {String}
   */
  ,sPriceHtml: function (type, checked, val, priceName, priceVal, priceDsc){
    if( !priceVal.blank() || !priceDsc.blank() ) {

      var priceFull = '<span>'+priceVal
      if(!priceVal.blank() && !priceDsc.blank())
        priceFull +=' <br>'
      priceFull += '<span>'+priceDsc+'</span></span>'

      return ''
      +'<div>'
      +' <input type='+type+' '+checked+' value='+val+' name="priceType">'
      +' <p>'
      +'  <strong>'+priceName+':</strong> '+priceFull
      +' </p>'
      +'</div>'
    }
    return "";
  }
  
  /**
   * Очистка заказа (полей окна и хранилища товаров)
   */
  ,Reset : function($super) {
    // !!! this.ResetStore()
    // Очищать хранилище нельзя, так как при ПОВТОРНОМ заказе
    // из формы на странице товара хранилище будет пустым
    // т.к. добавление товара в this.store[] происходит
    // в this.setFormData() и не вызывается повторно из this.Expand()

    $super();
    this.curForm.select('[name=quantity]')[0].value=1;
  }
  
});

var OrderWindow = Class.create(BaseOrderWindow, {

  /**
   * флаг что форма заказа как окно
   * @type {Boolean}
   */
   bAsWindow:false
  
  /**
   * Отображает окно "быстрого заказа"
   *
   * @param {String} $super
   * @param {String} id
   * @param {String} name
   * @param {String} price
   * @param {String} priceDsc
   * @param {String} priceRetail
   * @param {String} priceRetailDsc
   * @param {String} formId
   */
  ,Show : function ($super, id, name, price, priceDsc, priceRetail, priceRetailDsc, formId) {

    this.controller.view = this;
    
    this.setFormData(id, name, price, priceDsc, priceRetail, priceRetailDsc, formId)

    this.bAsWindow = true;

    this.Expand();

    ElPos('o_bar', 'r', -150, -50);

    new Draggable('o_bar', {handle:'o_title1'});
    $('o_title1').setStyle({cursor:'move'});

    $('o_bar').setStyle({display:'block'});

    return false; // for tag <a>
  }
  
  /**
   * Раскрывает окно(слой) заказа
   * на странице товара
   */
  ,Expand : function () {
    this.controller.view = this;
    
    if ("block" != $('o_info').getStyle('display'))
      $('o_info').setStyle({display:"block"})

    $('o_close').setStyle({display:"block"})
  }

  /**
   * Скрывает окно "быстрого заказа" | "слой заказа" 
   * на странице товара
   */
  ,Hide: function () {
    if (!$('o_bar'))
      return;

    if (this.bAsWindow)
      $('o_bar').style.display= "none";
    else
      $('o_info').style.display= "none";

    $('o_close').setStyle({display:"none"});
  }
});

var BasketWindow = Class.create(BaseWindow, {

  Init : function() {

     // basket window
     this.window = new Window({
        maximizable:false
       ,minimizable:false
       ,resizable:false
       ,hideEffect:Element.hide
       ,showEffect:Element.show
       ,className:"alphacube"
       ,title:'Корзина'
     });
  
     this.window.setContent('sfBasketD', true);
  }
  
  ,Show : function($super, loaderTarget, formId) {

    this.controller.view = this;
    
    oOrderWindow.Hide();
    
    if(!this.window)
      this.Init();
  
    this.bindForm(formId);    
    this.ReloadCaptcha(true);
    
    this.controller.Refresh(loaderTarget);
    
    return false; // for tag <a>
  }
  
  ,Refresh : function () {
    
    if(!this.window)
      return;

    if(!this.window.visible)
      this.window.showCenter(true, 110);
    
    this.BuildContent();
    this.UpdateWindowSize(false, true);
  }
  
  ,BuildContent : function() {
  
    var sRows="", c=0;
  
    if (this.controller.basketStore.length) {
  
      this.controller.basketStore.each(function(unit, i) {
        c++;
        sRows += ''
          +'<tr class='+(c%2 ? 'even' : 'odd')+'>'
            +'<td class=num>'+c+'</td>'
            +'<td class=name>'+unit.name+'</td>'
            +'<td class=prices>'+unit.HtmlPrices(i)+'</td>'
            +'<td class=quantity>'+unit.HtmlQuantity(i)+'</td>'
            +'<td class=del>'+unit.HtmlDelete(i)+'</td>'
          +'</tr>'
      }, this)
  
      $('sfBasketT').select('tbody')[0].replace(sRows);
    }
  
    if (sRows) {
      // sfBasketC - content, sfBasketE - empty
      $('sfBasketE').style.display = 'none';
      $('sfBasketC').style.display = '';
    }
    else {
      $('sfBasketE').style.display = '';
      $('sfBasketC').style.display = 'none';
    }
  }
  
  ,UpdateWindowSize : function (recalcWidth, recalcHeight) {

    var width = (undefined == recalcWidth
      ? this.window.width
      //: this.window.content.firstChild.scrollWidth
      : this.window.content.firstChild.scrollWidth
    )
    var height = (undefined == recalcHeight
      ? this.window.height
      //: this.window.content.firstChild.scrollHeight
      : this.window.content.firstChild.scrollHeight
    )
  
    this.window.setSize(width, height, true)
    // fix Chrome
    this.window.content.style.overflowX="hidden";
  }
  
  ,Reset : function ($super) {
    $super();
    this.controller.ResetStore();
    this.controller.UpdateQuantity();
  }
});

var FirmWindow = Class.create(BaseOrderWindow, {

   Init : function () {
  
    this.window = new Window({
       maximizable:false
      ,minimizable:false
      ,resizable:false
      ,hideEffect:Element.hide
      ,showEffect:Element.show
      ,className:"alphacube"
      ,title:'Информация'
      ,width:550
      ,height:440 //650
    });

    this.window.setContent('firm');
  }

  ,Show : function ($super, frmId, frmName, id, name, price, priceDsc, priceRetail, priceRetailDsc, formId) {

    this.controller.view = this;
    
    if(!this.window)
      this.Init();

    $('f_name').innerHTML = frmName;
    //$('f_region').innerHTML = region
    $('f_link').onclick = function(){setFirm(frmId); return false;};

    this.setFormData(id, name, price, priceDsc, priceRetail, priceRetailDsc, formId);

    this.window.showCenter(true, 110);

    return false; // for tag <a>
  }
});
//###### 



//###### UNITS
var OrderUnit = function(id, quantity, priceType) {
  return {
     u:id
    ,q:quantity || 1
    ,pt:priceType || 0
  }
};

var BasketUnit = function(data) {
  
  return Object.extend({
     id:null
    ,code:null
    ,name:null
    ,ad:null

    ,price:null
    ,idCurrencyPrice:null
    ,fullPrice:null

    ,priceRetail:null
    ,idCurrencyPriceRetail:null
    ,fullPriceRetail:null

    ,priceType:null
    ,quantity:null

    ,deleted:null

    ,HtmlPrices:function(i) {

      var html = '', chk;

      if (this.fullPrice) {

        chk = (1 == this.priceType ? 'checked' : "")

        html += '<input type=radio '+chk+' name=pt'+i+' onChange="oBasket.basketStore['+i+'].priceType = 1">'
        +this.fullPrice
      }

      if (this.fullPrice && this.fullPriceRetail)
        html += '<br>'

      if (this.fullPriceRetail) {

        chk = (2 == this.priceType ? 'checked' : "")

        html += '<input type=radio '+chk+' name=pt'+i+' onChange="oBasket.basketStore['+i+'].priceType = 2">'
        +this.fullPriceRetail
      }

      return html
    }
    ,HtmlQuantity:function(i) {
      return ''
        +'<input type=text value='+this.quantity+' onChange="oBasket.basketStore['+i+'].quantity = this.value">'
    }
    ,HtmlDelete:function(i) {
      return ''
        +'<input type=checkbox onChange="oBasket.basketStore['+i+'].deleted = this.checked">'
    }
  }, data);
}
//###### 

//###### ORDER
var Order = Class.create({

  /**
   * хранилище товаров заказа
   * массив объектов типа orderUnit
   * @type {Array}
   */
   store:[]

  /**
   * телефон
   * @type {String}
   */
  ,phone:""

  /**
   * имя продавца
   * @type {String}
   */
  ,name:""

  /**
   * примечание к заказу
   * @type {String}
   */
  ,note:""

  /**
   * значение капчи
   * @type {String}
   */
  ,captcha:""

  /**
   * url обработчика заказа
   * @type {String}
   */
  ,urlOrderHandler:'order.php?'

  /**
   * url генератора капчи
   * @type {String}
   */
  ,urlCaptcha:'libs/kcaptcha/?'


  // объект типа Window на будующее
  ,view:undefined 

  /**
   * метод инициализации
   *
   */
  ,Init : function() {

  }

  /**
   * Добавляет товар в заказ
   *
   * @param {OrderUnit} orderUnit
   */
  ,toOrder : function(orderUnit) {
    this.store.push(orderUnit)
  }


  /**
   * Заказ одного товара из "быстрого" окна заказа
   *
   * @param {} loaderTarget
   */
  ,Execute : function(loaderTarget) {
    
    this.buildOrderUnits();
    this.pickFormData();

    this.Send(loaderTarget);
    
    return false; // for submit action
  }

  /**
   * Метод подготавливает строки заказа 
   */
  ,buildOrderUnits : function() {

    // подготавливаем данные товара
    var curForm = this.view.curForm;
    this.store[0].q = curForm.select('[name=quantity]')[0].value;
    this.store[0].pt = curForm.select(':checked[name=priceType]').length
      ? curForm.select(':checked[name=priceType]')[0].value
      : 0
    ;
  }

  /**
   * Метод переносит информацию из полей 
   * формы заказа, в поля объекта заказа
   */
  ,pickFormData : function() {
    
    // данные пользователя
    var curForm = this.view.curForm;
    this.name = curForm.select('[name=name]')[0].value;
    this.phone = curForm.select('[name=phone]')[0].value;
    this.note = curForm.select('[name=note]')[0].value;
    this.captcha = curForm.select('[name=captcha]')[0].value;
  }
  
  /**
   * выполнение заказа
   *
   * @param {Object} loaderTarget
   * @param {Function} extSucc
   * @param {Function} extFail
   * @param {Object} scope
   */
  ,Send : function(loaderTarget, extSucc, extFail, scope ) {

    if (!this.phone || !this.captcha)
      return alert('Заполните все необходимые поля');

    extSucc = extSucc || function(){
      this.view.Hide();
      this.view.Reset();
    };
    
    extFail = extFail || function(){
      this.view.ReloadCaptcha(true);
    }

    scope = scope || this;
/*
    var params = Object.clone(this);
    delete params.urlCaptcha;
    delete params.urlOrderHandler;
    delete params.urlBasketHandler;
    delete params.curForm;
    delete params.view;
*/    
    var params = {
       store:this.store
      ,name:this.name
      ,phone:this.phone
      ,note:this.note
      ,captcha:this.captcha
    };

    Gate({
       url:this.urlOrderHandler
      ,params:{o:Object.toJSON(params)}
      ,onSuccess:function(info, data){
        extSucc.call(scope)
        alert(info)
      }
      ,onFailure:function(info, data){
        extFail.call(scope)
        alert(info)
      }
      ,loaderTarget:loaderTarget
    },this)
  }

  /**
   * Очистка хранилища позиций заказа
   */
  ,ResetStore : function() {
    this.store = [];
  }
});
//######


//###### BASKET
var Basket = Class.create(Order, {

  basketStore:[]
  ,urlBasketHandler:'basket.php?'
    
  /**
  * метод инициализации
  *
  */
  ,Init : function() {
    
    Gate({
      url:this.urlBasketHandler
      ,onSuccess:function(info, data){
      this.fillStoreFromJSON(data)
      this.UpdateQuantity()
      }
      ,loaderTarget:$('bgc').up('div[class=b_basket]')
    },this)    
  }

  ,toBasket : function(id, loaderTarget) {
   Gate({
      url:this.urlBasketHandler+'&b_add'
     ,params:{u:id}
     ,onSuccess:function(info, data){
       this.UpdateQuantity(data)
       alert(info)
     }
     ,loaderTarget:loaderTarget
   },this)

   return false; // for tag <a>
  }

  ,Refresh : function(loaderTarget) {
   Gate({
      url:this.urlBasketHandler
     ,onSuccess:function(info, data){
       this.fillStoreFromJSON(data);
       this.UpdateQuantity();
       this.view.Refresh();       
     }
     ,loaderTarget:loaderTarget
   },this)

   return false; // for tag <a>
  }

  ,Recount : function(loaderTarget) {

   var newStore = this.basketStore.reject(function(unit){
     return unit.deleted;
   })

   Gate({
      url:this.urlBasketHandler+'&b_upd'
     ,params:{b:Object.toJSON(newStore)}
     ,onSuccess:function(info, data){
       // только после Success обновлять basketStore 
       this.basketStore = newStore;
       this.UpdateQuantity();
       this.view.Refresh();
     }
     ,loaderTarget:loaderTarget
   }, this)
  }

  ,buildOrderUnits : function() {

   // создаём OrderUnit из BasketUnit
   this.basketStore.each(function(unit){
     this.toOrder(new OrderUnit(unit.id, unit.quantity, unit.priceType));
   }, this);
  }

  /**
  * Очистка хранилища позиций корзины
  */
  ,ResetStore : function() {
   this.basketStore = [];
  }

  /**
  * Метод конвертирует JSON ответ 
  * в массив обьектов BasketUnit 
  */
  ,fillStoreFromJSON : function(data) {
   for (var i=0, l=data.length; i<l; i++)
     this.basketStore[i] = new BasketUnit(data[i]);     
  }

  /**
  * метод обновляет счетчик товаров в корзине
  */
  ,UpdateQuantity : function(quantity) {
   if ($('bgc'))
     $('bgc').innerHTML = parseInt(quantity) || this.basketStore.length;
  }
});
//######


var oOrder = new Order();
var oBasket = new Basket();
var oOrderWindow = new OrderWindow(oOrder); 
var oBasketWindow = new BasketWindow(oBasket); 
var oFirmWindow = new FirmWindow(oOrder);
