var Globals = { ItemsData: [], FullPrice: 0, RONSign: String.fromCharCode(187) };

var FormHandlerInstanceManager = {
    _instance: null,
    Get: function(e, form, elementsToWatch, cookieNameTransform){
        if(this._instance == null)
            this._instance = new FormHandler(e, form, elementsToWatch, cookieNameTransform);
        if(typeof e != 'undefined' && typeof e.persisted != 'undefined' && e.persisted == true)
            this._instance.PersistInit();
        return FormHandler._instance;
    }
};

function FormHandler(e, form, elementsToWatch, cookieNameTransform)
{
    var tthis = this;
    this._form = (typeof form == 'string' ? document.forms[ form ] : form);
    
    var rules = [ 
        //new FormDependencyRule('priority_row', 'requestmode==0', function(result){ return tthis._PriorityCallback(result); }),
        new FormDependencyRule('billpayertax_row', 'billpayertype==1'),
        new FormDependencyRule('billpayeremail_row', '0'),
        new FormDependencyRule('billpayerfax_row', '0'),
        new FormDependencyRule('billpayerbankaccount_row', 'billpayertype==1'),
        new FormDependencyRule('recipientdata_row', 'recipientaddr==1'),
        //new FormDependencyRule('contactpersonaddr2_row', '0'),
        new FormDependencyRule('mediatorname_row', 'mediatedbuy==1'),
        new FormDependencyRule('orderid_row', 'mediatedbuy==1')
    ];
    
    this._depHandler = new FormDependencyHandler(this._form, rules);
    this._depHandler.RegisterChangeCallback(new CallBackFunction('hostingOptions', function(e){ tthis._OptionHandlerCallback(e); }));
    this._depHandler.RegisterChangeCallback(new CallBackFunction('priceCounter', function(e){ tthis._CalculatePriceSumCallback(e); }));
    this._depHandler.RegisterChangeCallback(new CallBackFunction('respondercoupon', function(e){ tthis._CalculatePriceSumCallback(e); }));
    
    var elsToWatch = new Array();
    for(var optionName in cu.options)
    {
        if(Helpers.GetInputValue(optionName, this._form, true) !== null)
            elsToWatch.push(optionName);
    }
    this._depHandler.AddElementsToWatch(elsToWatch);
//    this._depHandler.AddElementsToWatch(elementsToWatch);
    this._depHandler.Attach();
    
    this._dataHandler = new FormDataHandler(this._form, cookieNameTransform, this._ShowDataError.bind(this));
    this._dataHandler.Init();
    this._dataHandler.RegisterChangeCallback( new CallBackFunction('getItemsData', function(e){ return tthis._GetItemsDataCallback(e); }, false) );
    this._dataHandler.RegisterChangeCallback( new CallBackFunction('dataValidityChecker', function(e){ return tthis._DataValidityCheckerCallback(e); }, false) );
    this._dataHandler.Load();
}

FormHandler.prototype.PersistInit = function()
{
    this._dataHandler.RestoreItems();
}

//hibajelentes a kliensnek
FormHandler.prototype._ShowError = function(msg)
{
    alert(msg);
}

FormHandler.prototype._ShowDataError = function()
{
    this._ShowError(texts['data_not_set_or_incorrect']);
}

FormHandler.prototype._RoundNum = function(num)
{
    return Math.round(num*100)/100;
}

FormHandler.prototype._ConvertToRON = function(price)
{
    var convRatio = parseFloat(cu.configuration.priceConversionRatio);
    return price*convRatio;
}

FormHandler.prototype._GetCMPriceText = function(price)
{
    if(cu.configuration.enablePriceConversion == 0)
        return '';
    var priceInRON = this._ConvertToRON(price);
    return priceInRON>0 ? "("+ Globals.RONSign +" "+ this._RoundNum(priceInRON) +' RON)' : '';
}

FormHandler.prototype._GetCombinedOptionValue = function(option, selectedValue, valueName) //visszaadja az elem arat figyelembe veve a felulirasokat (host es elem)
{
    var baseValue = typeof option.items[selectedValue][valueName] != 'undefined' && option.items[selectedValue][valueName] !== null  //eloszor megnezi, hogy a selectedItemben van e ilyen property
        ? option.items[selectedValue][valueName]           //ha igen, akkor ez a prioritasos
        : (typeof option[valueName] != 'undefined' ? option[valueName] : null);  //ha nincs akkor megnezi, van e kozos ilyen property
    
	if ( typeof option.items[selectedValue] != 'undefined' && typeof option.items[selectedValue]['coupon'] != 'undefined' ) {
    	var respcoupon = Helpers.GetInputValue('respondercoupon', this._form);
		if ( respcoupon == null ) respcoupon = 0;
		if ( typeof option.items[selectedValue]['coupon']['respondercoupon'][respcoupon][valueName] != 'undefined' )
			baseValue = option.items[selectedValue]['coupon']['respondercoupon'][respcoupon][valueName];
	}
	
    return baseValue;
}

FormHandler.prototype._CalcItemPrice = function(item)
{
    var priceFollowing = priceNow = 0;
    
    priceNow = ((item.price*(1+item.percentfirst/100) - item.discountfirst ) + item.onetimeprice - item.onetimediscount) * item.quantity;
    priceFollowing = (item.pricefollowing*(1+item.percentfollowing/100) - item.discountfollowing ) * item.quantity 
    
    return {'priceNow': priceNow, 'priceFollowing': priceFollowing}; 
}

//az osszes ar itt van szamolva: domain, hosting, option, osszes ar
FormHandler.prototype._CalculatePriceSumCallback = function(e)
{
    var output = '';
    var fullPrice = 0;
    var priceNow = 0; 
    var priceYearly = 0;
    Globals.ItemsData = new Array();
    Globals.ItemsDataDef = new Array();
    
    var getObjectNthPropertyName = function(obj,propNum){ for(var propName in obj){ if(propNum==0){return propName;}else{propNum--;} } }
    
    //option ar szamolas---------------------------------------------------
    output = '';
    
    var optionPriceSum = {'onetimePrice': 0, 'priceNow': 0};
    var tthis = this;
    for(var optionName in cu.options)
    {
        var getOptionPrice = function(option, selectedValue, optionData) //visszaadja az option elemenek egyszeri es havi arat
        {
            var basePrice = tthis._GetCombinedOptionValue(option, selectedValue, "price");
            var onetimeprice = tthis._GetCombinedOptionValue(option, selectedValue, "onetimeprice");
            var quantity = tthis._GetCombinedOptionValue(option, selectedValue, "quantity");
            var percentfirst = tthis._GetCombinedOptionValue(option, selectedValue, "percentfirst");
            var discountfirst = tthis._GetCombinedOptionValue(option, selectedValue, "discountfirst");
            var percentfollowing = tthis._GetCombinedOptionValue(option, selectedValue, "percentfollowing");
            var discountfollowing = tthis._GetCombinedOptionValue(option, selectedValue, "discountfollowing");
            var onetimediscount = tthis._GetCombinedOptionValue(option, selectedValue, "onetimediscount");
            var pricemonth = tthis._GetCombinedOptionValue(option, selectedValue, "pricemonth");
            var info = tthis._GetCombinedOptionValue(option, selectedValue, "info");
            var monthFollowing = tthis._GetCombinedOptionValue(option, selectedValue, "monthfollowing");
            monthFollowing = monthFollowing===null ? (pricemonth<12 ? pricemonth : 12) : monthFollowing;
            
            var price = pricemonth!=0 ? basePrice : 0;
            //var monthFollowing = pricemonth;
            //var price2 = basePrice;
            var price2 = pricemonth!=0 ? basePrice*(monthFollowing/pricemonth) : 0;
            
            var pn = (price*(1+percentfirst/100) - discountfirst ) * quantity;
            var pf = (price2*(1+percentfollowing/100) - discountfollowing ) * quantity;
            var otp = (onetimeprice - onetimediscount)* quantity;
            
            if(optionData != null)
            {
                //az ujraszamolt arak, amit a szerverre kell kuldeni
                try{
                    //minden erteket atirunk amit az option kivalasztott eleme felulirna
                    for(var propertyName in option.items[selectedValue])
                    {
                        try{
                            optionData[propertyName] = tthis._GetCombinedOptionValue(option, selectedValue, propertyName);
                        }catch(ex)
                        {
                            Helpers.Log('_CalculatePriceSumCallback >> exception: %o', ex);
                        }
                    }
                }catch(ex)
                {
                    Helpers.Log('_CalculatePriceSumCallback >> exception2: %o', ex);
                }
                optionData.price = price;
                optionData.pricemonth = pricemonth; // option.pricemonth; lehet, hogy így nem lesz jó a formHandlerbe , a cél, hogy 6 havi responert meg tudjon rendelni
                optionData.monthfollowing = monthFollowing;
                optionData.pricefollowing = price2;
                optionData.onetimediscount = onetimediscount;
                optionData.discountfirst = discountfirst;
                optionData.discountfollowing = discountfollowing;
                //commissionfirst es commissionfollowing kiszamolva
                var finPrice = tthis._CalcItemPrice(optionData);
                optionData.commissionfirst = Math.max(optionData.commissionfirst!==null ? optionData.commissionfirst-optionData.discountfirst-optionData.onetimediscount : finPrice.priceNow, 0);
                optionData.commissionfollowing = Math.max(optionData.commissionfollowing!==null ? optionData.commissionfollowing-optionData.discountfollowing : finPrice.priceFollowing, 0);
                optionData.info = info;
            }
            
            return {'onetimePrice':otp, 'priceNow': pn, 'priceFollowing': pf, 'optionData': optionData};
        }
        
        var val = Helpers.GetInputValue(optionName, this._form, true);
        var sel = Helpers.GetElement(optionName, this._form);
        var op = Helpers.GetItemFromObjectListByProp(cu.options, 'id',optionName);
        if(!val)
            continue;
        if(op != null && op.texttype)
        {
            var optionData = Helpers.CopyObjectData(op);
            optionData.info = val;
            Globals.ItemsData.push(optionData);
            continue;
        }
        if(val != '0' || op.firstisdisabled==0)
        {
            op.ordername = Helpers.ReplaceParams(op.ordername, '$orderitem', this._GetCombinedOptionValue(op, val, "orderitem"), optionName+'_oitem');
            op.invoicename = Helpers.ReplaceParams(op.invoicename, '$invoiceitem', this._GetCombinedOptionValue(op, val, "invoiceitem"), optionName+'_iitem');
            
            var optionData = Helpers.CopyObjectData(op);
            var opPrice = getOptionPrice(op, val, optionData);
            optionData = opPrice.optionData;//Helpers.CopyObjectData(optionData, opPrice.optionData);
            
            optionPriceSum.priceNow += opPrice.priceNow;
            optionPriceSum.onetimePrice += opPrice.onetimePrice;
            fullPrice += opPrice.priceNow + opPrice.onetimePrice;
            
            var optionDataDef = Helpers.CopyObjectData(op);
            var valDef = getObjectNthPropertyName(op.items, op.firstisdisabled ? 1 : 0); 
            var opPriceDef = getOptionPrice(op, valDef, optionDataDef);
            optionDataDef = opPriceDef.optionData;
            
            if ( optionData.price > 0 || optionData.pricefollowing > 0 || optionData.onetimeprice > 0 ) {
				Globals.ItemsData.push(optionData);
            	Globals.ItemsDataDef.push(optionDataDef);
			}
        }
        for(var i=0; i<sel.options.length; i++) //az select-ekben at kell szamolni az arakat, majd atirni oket, hogy lassa a juzer
        {
            var opPrice = getOptionPrice(op, sel.options[i].value);
            sel.options[i].text = Helpers.ReplaceParams(sel.options[i].text, '$pricenow', this._RoundNum(opPrice.priceNow + opPrice.onetimePrice), optionName+i.toString());
        }
    }
    if(optionPriceSum.onetimePrice>0 || optionPriceSum.priceNow>0)
        output += ""
                + (optionPriceSum.onetimePrice>0 ? this._RoundNum(optionPriceSum.onetimePrice) : '') 
                + (optionPriceSum.onetimePrice>0 && optionPriceSum.priceNow>0 ? '+': '') 
                + (optionPriceSum.priceNow>0 ? this._RoundNum(optionPriceSum.priceNow) : '') 
                + ' ' + texts['centralmoneydesc']
                + this._GetCMPriceText(optionPriceSum.onetimePrice) + this._GetCMPriceText(optionPriceSum.priceNow)
                + '+'+ texts['vatname'] +"\n";
    
    //option ar szamolas---------------------------------------------------//
    
    //veg ar szamolas---------------------------------------------------
    Helpers.SetInputValue('pricenow', this._form, output);
    Globals.FullPrice = fullPrice;
    //veg ar szamolas---------------------------------------------------//
}

//megjeleniti/eltunteti a kommentarokat az optionokhoz
FormHandler.prototype._OptionHandlerCallback = function(e)
{
    var descr, idescr, o, option;
    for(var optionName in cu.options)
    {
        option = cu.options[optionName];
        o = Helpers.GetElement(option.id +'_row', this._form);
        if(o == null)
            continue;
        descr = Helpers.GetElement(optionName + '_descr', this._form);
        idescr = Helpers.GetElement(optionName + '_idescr_row', this._form);
        
        //kommentar megjelenitese 
        if(option.descr != null && option.descr.length>0)
        {
            //Helpers.SetText(optionName + '_descr', option.descr);
            descr.style.display = '';
        }else
            descr.style.display = 'none';
        var selectedValue = Helpers.GetInputValue(optionName, this._form);
        
        //selected option kommentar megjelenitese 
        if(option.items[selectedValue] && option.items[selectedValue].descr != null && option.items[selectedValue].descr.length>0)
        {
            Helpers.SetText(optionName + '_idescr', option.items[selectedValue].descr);
            idescr.style.display = '';
        }else
            idescr.style.display = 'none';
    }
}

FormHandler.prototype._DataValidityCheckerCallback = function(e)
{
    var isOK = true;
    if(Helpers.GetInputValue('contactpersonemail', this._form) != Helpers.GetInputValue('contactpersonemailrep', this._form))
    {
        $('contactpersonemail_row').className = 'row_error';
        $('contactpersonemailrep_row').className = 'row_error';
        isOK = false;
    }
    
    return !isOK; //breaks if retVal == true
}

FormHandler.prototype._GetItemsDataCallback = function(e)//el kell kuldeni a szerverre a tetelek alapertelmezeseit es aktualis ertekeit is
{
    for(var optionName in cu.options)
    {
        var selectedValue = Helpers.GetInputValue(optionName, this._form, true);
        if(selectedValue===null || (selectedValue == '0' && cu.options[optionName].firstisdisabled==1))
            continue;
        if(selectedValue == '0') //ha a firstdisabled miatt volt atengedve az elem, akkor at kell allitani a value-jat, mert a resultForm nem fogja megmutatni
        {
            var sel = Helpers.GetElement(optionName, this._form);
            var opObj = sel.options[ sel.selectedIndex ];
            if(opObj.value == '0')
                opObj.value = '__0';
        }
    }
    
    if(Globals.ItemsDataDef.length == 0 || Globals.ItemsData.length == 0)
    {
        this._ShowError(texts['no_items_selected']);
        return true;
    }
    
    var tthis = this;
    var prepareItemListToSend = function(itemList)
    {
        //kerekiteni kell az arakat 2 tizedesre
        for(var i=0; i<itemList.length; i++)
        {
            for(var prop in itemList[i])
            {
                if(itemList[i][prop]!='' && !isNaN(itemList[i][prop]))
                {
                    try{
                        itemList[i][prop] = tthis._RoundNum(itemList[i][prop]);
                    }catch(ex)
                    {
                        Helpers.Log('_GetItemsDataCallback >> exception2: %o', ex);
                    }
                }
            }
        }
        //json-olja a listat, hogy kompatibilis legyen a szerverrel
        var valStr = JSON.stringify(itemList);
        valStr = valStr.replace(/"/gi, "'"); 
        return valStr;
    }
    
    //--------------tetelek aktualis ertekei
    itemsStr = prepareItemListToSend(Globals.ItemsData);
    Helpers.SetInputValue('itemsdata', this._form, itemsStr);
    
    //--------------tetelek default ertekei
    itemsDefStr = prepareItemListToSend(Globals.ItemsDataDef);
    Helpers.SetInputValue('itemsdefault', this._form, itemsDefStr);
    
    //--------------teljes ar
    Helpers.SetInputValue('fullprice', this._form, this._RoundNum(Globals.FullPrice));
}

function CopyFromBillPayer()
{
    var myform = document.domhostForm;
	
	if ( Helpers.GetInputValue('billpayertype', myform) == 0 && Helpers.GetInputValue('billpayername', myform) != null ) { 
		Helpers.SetInputValue('contactpersonname', myform, Helpers.GetInputValue('billpayername', myform));
		Helpers.SetInputValue('contactpersonnick', myform, Helpers.GetInputValue('billpayername', myform));
	}
    if ( Helpers.GetInputValue('contactpersonshire', myform) != null && Helpers.GetInputValue('billpayershire', myform) != null ) 
		Helpers.SetInputValue('contactpersonshire', myform, Helpers.GetInputValue('billpayershire', myform));
    if ( Helpers.GetInputValue('contactpersonzip', myform) != null && Helpers.GetInputValue('billpayerzip', myform) != null ) 
		Helpers.SetInputValue('contactpersonzip', myform, Helpers.GetInputValue('billpayerzip', myform));
    if ( Helpers.GetInputValue('contactpersoncountry', myform) != null && Helpers.GetInputValue('billpayerstreet', myform) != null ) 
		Helpers.SetInputValue('contactpersoncountry', myform, Helpers.GetInputValue('billpayerstreet', myform));
    if ( Helpers.GetInputValue('contactpersonstreet', myform) != null && Helpers.GetInputValue('billpayeraddr', myform) != null ) 
		Helpers.SetInputValue('contactpersonstreet', myform, Helpers.GetInputValue('billpayeraddr', myform));
    if ( Helpers.GetInputValue('contactpersonemail', myform) != null && Helpers.GetInputValue('billpayeremail', myform) != null ) 
		Helpers.SetInputValue('contactpersonemail', myform, Helpers.GetInputValue('billpayeremail', myform));
    if ( Helpers.GetInputValue('contactpersonemailrep', myform) != null && Helpers.GetInputValue('billpayeremail', myform) != null ) 
		Helpers.SetInputValue('contactpersonemailrep', myform, Helpers.GetInputValue('billpayeremail', myform));
    if ( Helpers.GetInputValue('contactpersonmobil', myform) != null && Helpers.GetInputValue('billpayertel', myform) != null ) { 
		var tel = Helpers.GetInputValue('billpayertel', myform);
		if ( tel.search('20')>=0 || tel.search('30')>=0 || tel.search('70')>=0 )
			Helpers.SetInputValue('contactpersonmobil', myform, tel);
		else if ( Helpers.GetInputValue('contactpersontel', myform) != null ) Helpers.SetInputValue('contactpersontel', myform, tel);
	}
    if ( Helpers.GetInputValue('contactpersonfax', myform) != null && Helpers.GetInputValue('billpayerfax', myform) != null ) 
		Helpers.SetInputValue('contactpersonfax', myform, Helpers.GetInputValue('billpayerfax', myform));
		
	// kapcsolati email cím módosítás miatt újra kell ellenorizni az adatokat
	var element = Helpers.GetElement('contactpersonemail', myform);
	var evt;
	
	if (document.createEventObject){
        // dispatch for IE
        evt = document.createEventObject();
        element.fireEvent('onchange',evt);
    }
    else{
        // dispatch for firefox + others
        evt = document.createEvent("HTMLEvents");
        evt.initEvent('change', true, true ); // event type,bubbling,cancelable
        element.dispatchEvent(evt);
    }	
}
