var DC = {
	
	debug:false, mask:undefined, popup:undefined, maskStyle:{backgroundColor:'black',opacity:'0.8',zIndex:100,width:(document.viewport.getWidth()+'px'),height:(document.viewport.getHeight()+'px'),position:'fixed',top:'0px',left:'0px'},
	
	log:function(){
	},

	render:function(url, style, data){
		
		this.disableInput();
		
		if(Object.isUndefined(this.popup) === false){
			
			Element.remove(this.popup);
		}
		
		if(style === false || Object.isUndefined(style) || style === null){
			
			style		= {width:'900px',height:'550px',backgroundColor:'white',borderColor:'black',border:'1px solid',position:'fixed',zIndex:101};
			style.left	= (document.viewport.getWidth()/2)-450 + 'px';
			style.top	= (document.viewport.getHeight()/2)-275 + 'px';
		}
		
		Element.insert(document.body,{
			
			bottom: new Element('div', {id:'dcPopup'}).setStyle(style)
		});
		
		this.popup = $('dcPopup');
		
		if(data == null){
		
			new Ajax.Updater('dcPopup', url, {onSuccess:this.onRenderSuccess.bind(this), onFailure:this.onRenderFailure.bind(this), evalScripts:true, evalJSON:true});
		}
		else{
			
			new Ajax.Updater('dcPopup', url, {onSuccess:this.onRenderSuccess.bind(this), onFailure:this.onRenderFailure.bind(this), evalScripts:true, evalJSON:true, parameters:Form.serializeElements(data)});
		}
	},
	
	onRenderSuccess:function(){
		
		this.popup.show();
	},
	
	onRenderFailure:function(){
		
		alert("Error!\r\nSorry we could not load the feature you are after. Please try again.");
		
		this.enableInput();
	},
	
	disableInput:function(){
		
		if(Object.isUndefined(this.mask)){
			
			Element.insert(document.body,{
				
				bottom: new Element('div', {id:'dcMask'}).setStyle(this.maskStyle)
			});
			
			this.mask = $('dcMask');
		}
		
		this.mask.show();
		
		$(document.body).setStyle({overflow:'hidden'});
	},
	
	enableInput:function(reload){
		
		if(Object.isUndefined(this.popup) === false){
			
			this.popup.hide();
			
			if(reload === true)
				return window.location.reload();
		}
		
		if(Object.isUndefined(this.mask) === false){
			
			this.mask.hide();
		}
		
		$(document.body).setStyle({overflow:'auto'});
	}
};

function editKpiPortfolioCampaigns(clientId, portfolioId)
{
	__style = {width:'900px',height:'550px',backgroundColor:'white',borderColor:'black',border:'1px solid',position:'fixed',zIndex:101};
	__style.left	= (document.viewport.getWidth()/2)-450 + 'px';
	__style.top		= (document.viewport.getHeight()/2)-275 + 'px';
	
	DC.render('/key_performance_indicators/assign_campaigns/'+clientId+'/'+portfolioId, __style);
}

function editKpiPortfolio(clientId, portfolioId, accountWide){
	
	__style = {width:'900px',height:'550px',backgroundColor:'white',borderColor:'black',border:'1px solid',position:'fixed',zIndex:101};
	__style.left	= (document.viewport.getWidth()/2)-450 + 'px';
	__style.top		= (document.viewport.getHeight()/2)-275 + 'px';
	
	DC.render('/key_performance_indicators/edit_advanced/'+clientId+'/'+portfolioId+'/'+(accountWide ? 1 : 0), __style);
}

function assignCampaign()
{
	
}

function removeCampaign()
{
	
}

var KeyPerformanceIndicatorAlgorithms = {
	
	ctr:{equation:'(#{clicks}/#{impressions})*100',decimals:2},
	
	cpc:{equation:'#{spend_dollars}/#{clicks}',decimals:2},
	
	cvr:{equation:'(#{conversions}/#{clicks})*100',decimals:2},
	
	cpa:{equation:'(Number(#{conversions}) == 0) ? 0 : #{spend_dollars}/#{conversions}',decimals:2},
	
	spend_dollars:{equation:'#{monthly_budget}*(#{spend}/100)',decimals:2},
	
	clicks:{
		
		equations:{
		
			cpc:'#{spend_dollars}/#{cpc}',
		
			ctr:'#{impressions}*(#{ctr}/100)',
		
			conversions:'(Number(#{cvr})==100 || Number(#{clicks}) == 0) ? #{conversions} : (Number(#{conversions}) == 0 ? #{clicks} : #{conversions}*(100/#{cvr}))',
		
			cvr:'#{conversions}*(100/#{cvr})'
		},
		
		decimals:0
	},
	
	impressions:{
		
		equations:{
		
			ctr:'(Number(#{ctr}) == 0) ? #{clicks} : #{clicks}*(100/#{ctr})',
		
			clicks:'(Number(#{ctr})==100 || Number(#{impressions}) == 0) ? #{clicks} : (Number(#{ctr}) > 0 ? #{clicks}*(100/#{ctr}) : 0)'
		},
		
		decimals:0
	},
	
	conversions:{
		
		equations:{
		
			cpa:'#{spend_dollars}/#{cpa}',
		
			cvr:'#{clicks}*(#{cvr}/100)',
			
			clicks:'(Number(#{conversions}) > Number(#{clicks})) ? #{clicks} : #{conversions}'
		},
		
		decimals:0
	}
};

/**
 * KeyPerformanceIndicator Portfolio Object
 * 
 * Handles ALL core client side KPI Metric calculations and logic
 */
var KeyPerformanceIndicatorPortfolio = Class.create({

    id:0, name:'', metrics:new Hash(), cache:new Hash(), freeform:false, formid:'formKeyPerformanceIndicators', availableCampaigns:null, assignedCampaigns:null,

    /**
     * Initialise KeyPerformanceIndicatorPortfolio; constructor method
     * Assigns appropriate form element for our portfolio inputs
     * 
     * @param {String} form
     */
    initialize:function(form, autoupdate){
		
		if(Object.isUndefined(form) === true && (!$(this.formid) || Object.isUndefined($(this.formid)))){
			
			alert('');
			
			return;
		}
	
		if($(form) && $(form).tagName == 'FORM'){
			
			this.form = $(form);
		}
		else if($(this.formid) && $(this.formid).tagName == 'FORM'){
			
			this.form = $(this.formid);
		}
		else{
			
			alert('');
			
			return;
		}
		
		//Event.observe($('ctlRemoveCloseKpi'), 'click', this.remove.bind(this));
		Event.observe($('ctlSaveCloseKpi'), 'click', this.save.bind(this));
		
		this.form.getElements().each(this.bindInputs, this);
		
		if(autoupdate) this.updateMetric($('spend'));
    },

    /**
     * Primary method for capturing KPI form input change. checks for valid Object reference and if portfolio requires cascading updates
     * 
     * @param {Object} event
     */
	update:function(event){
		
    	if(Object.isUndefined(event.element()) === false && this.freeform === false) this.updateMetric(event.element());
    },
	
	/**
	 * Primary method for updating individual metrics in the KPI portfolio.
	 * Also responsible for recursively calling dependants of the active metric to cascade values correctly
	 * 
	 * @param {Object} metric
	 * @param {Object} requestingmetric
	 * @param {Object} trace
	 */
	updateMetric:function(metric, requestingmetric, trace){
		
		// check & instantiate trace Array; and store current metric
		if(Object.isArray(trace) === false) trace = []; trace.push(metric.kpi);
		
		// check if metric update was called from another metric (cascading)
		if(Object.isUndefined(requestingmetric) === true || requestingmetric == null){
        
            // make sure a valid value has been entered
			if(!isNaN($F(metric)) && $F(metric) >= 0){
            
				// check metric against any anchored metrics; return now if invalid
				if(this.validateMetric(metric) === false) return;
				
				// cache new value for metric
			    this.cache.set(metric.kpi, $F(metric));
									
			    // iterate through ALL of this metrics dependants;
				// dependants are those which derive their own value (in one way or another) from the current metric
				metric.dependants.each(function(dependant){
											
					// ensure dependant is a valid Object, and that its either not an anchor or its value is zero
					// anchored metrics cannot be changed by another metric (cascading)
					if($(dependant) && Object.isUndefined($(dependant)) === false && ($(dependant).anchor === false || $F($(dependant)) == 0)){
						
						// recursively call update on dependant metric
						this.updateMetric($(dependant), metric, trace);	
					}
					// dependant is our anchored metric; so tread uniquely
					else if($(dependant).anchor === true){
						
						// iterate through ALL of the anchors dependants
						$(dependant).dependants.each(function(subdependant){
							
							// make sure the dependant metric is not the same as the current metric we are processing; we dont want invinite loops
							if($(subdependant) !== metric){
								
								// recursively call update on dependant metric
								this.updateMetric($(subdependant), $(dependant), trace);									
							}
							
						}, this);
					}
					
				}, this);
            }
            else {
            
                // metrics new value is invalid; roll back to last cached version
				//metric.value = this.cache[metric.kpi];
				metric.value = this.cache.get(metric.kpi);
            }
        }
		// metric update triggered by another metric (cascading)
		else{
			
			// store requesting metric into our trace collection
			trace.push(requestingmetric.kpi);
			
			__requiredMetrics = this.findMetrics(metric, requestingmetric);
			
			__values = {}; __values[metric.kpi] = $F(metric);
			
			__zeroValue = false,
			
			// iterate through metrics dependencies
			// dependencies are metrics which are required in order to succesfully re-calculate the active metrics value
			metric.dependencies.each(function(dependency){
				
				// ensure dependency is a valid Object
				if($(dependency) && Object.isUndefined($(dependency)) === false){
				   
				    // check if we actually needs this metrics value for our calculation
					if(__requiredMetrics.indexOf(dependency) >= 0){
				   
						// ensure value is valid
						if((!isNaN($(dependency).getValue()) && $(dependency).getValue() > 0) || $(dependency).allowzero === true){
														
							// store 
							__values[dependency] = this.metrics.get(dependency).getValue();
						}
						else{
							
							__zeroValue = true;
						}						
					}
				}
				
			}, this);
			
			// if one of our required metrics returned a zero value; return now as we cannot calculate correctly
			if(__zeroValue === true) return;
			
			// update metric based on new calculate value
			metric.value = this.calculateMetricValue(metric, requestingmetric, __values);

			if(this.metrics.get(this.anchor).dependencies.indexOf(metric.kpi) >= 0){
				
				if(this.validateMetric(metric, requestingmetric) === false){
					
					metric.value = this.cache.get(metric.kpi);
				}
			}
			
			// cache new value
			//this.cache[metric.kpi] = $F(metric);
			this.cache.set(metric.kpi, $F(metric));

            // iterate through ALL of this metrics dependants;
            // dependants are those which derive their own value (in one way or another) from the current metric			
			metric.dependants.each(function(dependant){
                    
                // ensure dependant is a valid Object, and that its either not an anchor or its value is zero, and that has not already been updated via our trace
                // anchored metrics cannot be changed by another metric (cascading)
				if($(dependant) && Object.isUndefined($(dependant)) === false && ($(dependant).anchor === false || $F($(dependant)) == 0) && $(dependant) !== requestingmetric && trace.indexOf(dependant) == -1){
                    
					// recursively call update on dependant metric
					this.updateMetric($(dependant), metric, trace);    
                }
				// dependant is our anchored metric; so tread uniquely
				else if($(dependant).anchor === true){
					
					// iterate through ALL of the anchors dependants
					$(dependant).dependants.each(function(subdependant){
                        
                        // make sure the dependant metric is not the same as the current or requsted metric we are processing or part of our trace; we dont want invinite loops
					    if($(subdependant) !== metric && $(subdependant) !== requestingmetric && ($(subdependant).anchor === false || $F($(subdependant)) == 0) && trace.indexOf(subdependant) == -1){
                            
							// recursively call update on dependant metric
							this.updateMetric($(subdependant), $(dependant), trace);                                   
                        }
                        
                    }, this);
				}
                
            }, this);
		}
	},
	
	/**
	 * Validates the active metrics' value to ensure it doesnt violate any mathematical logic for how KPIs relate
	 * 
	 * @param {Object} metric
	 */
	validateMetric:function(metric, requestingmetric){
		
		// basic check to make sure doesnt exceed any min/max thresholds
		if(this.metrics.get(metric.kpi).min != null){
			
			if(Number($F(metric)) < Number(this.metrics.get(metric.kpi).min)){
			
				metric.value = this.cache.get(metric.kpi);
				
				return false;
			}
		}
		
		if(this.metrics.get(metric.kpi).max != null){
			
			if(Number($F(metric)) > Number(this.metrics.get(metric.kpi).max)){
				
				metric.value = this.cache.get(metric.kpi);
				
				return false;
			}
		}
		
		// switch logic based on requesting metric
		switch(metric.kpi){
			
			// impressions
			case 'impressions':
			
			    // check and apply validation if CPC is our main (anchor) metric
				if(this.anchor === 'cpc'){
					
					// we dont allow less Impressions than Clicks; not physically possible
					if(Number($F(metric)) < Number($F(this.metrics.get('clicks')))){
						
						//alert('Error!\r\n\r\nYour CPC is currently fixed at: $' + $F(this.metrics.get('cpc')) + '\r\nTo achieve this you must account for at least ' + $F(this.metrics.get('clicks')) + ' Impressions (with 100% CTR)');
						
						metric.value = this.cache.get(metric.kpi);
						
						return false;
					}
				}
				
				// check and apply validation if CTR is our main (anchor) metric
				if(this.anchor === 'ctr'){
					
					// check for a CTR less than 10%; means number of Impressions must be divisible by 10 (at least 10 Impressions)
					if(Number($F(this.metrics.get('ctr'))) <= 10 && Number($F(metric)) < 10){
						
						//alert('error');
						
						metric.value = this.cache.get(metric.kpi);
						
						return false;
					}
					
					// check for a CTR less than 20%; means number of Impressions must be divisible by 5 (at least 5 Impressions)
					if(Number($F(this.metrics.get('ctr'))) <= 20 && Number($F(metric)) < 5){
						
						//alert('error');
						
						metric.value = this.cache.get(metric.kpi);
						
						return false;
					}
					
					// check for a CTR less than 50%; means number of Impressions must be divisible by 4 (at least 4 Impressions)
					// note: we could set this to 3 Impressions for the 30-50% CTR range, but not worth it
					if(Number($F(this.metrics.get('ctr'))) < 50 && Number($F(metric)) < 4){
						
						//alert('error');
						
						metric.value = this.cache.get(metric.kpi);
						
						return false;
					}
				}
				
				if(this.anchor === 'clicks'){
					
					if(Number($F(this.metrics.get('clicks'))) > Number($F(metric))){
						
						//alert('error');
						
						metric.value = this.cache.get(metric.kpi);
						
						return false;
					}
				}
				
			break;
			// clicks
			case 'clicks':
			
			    // check and apply validation if CPC is our main (anchor) metric
				if(this.anchor === 'cpc' && (Object.isUndefined(requestingmetric) === false && requestingmetric.kpi != 'cpc')){
					
					// essentially we can NOT change Clicks if CPC is our anchor; since our Spend (budget) is also an anchor and CPC derives from this also
					if(Number($F(metric)) != Number(this.cache.get('clicks'))){
						
						//alert('Error!\r\n\r\nYour CPC is currently fixed at: $' + $F(this.metrics.get('cpc')) + '\r\nAs such you must achieve ' + Math.round($F(this.metrics.get('spend_dollars'))/$F(this.metrics.get('cpc'))) + ' Clicks');
						
						metric.value = this.cache.get(metric.kpi);
						
						return false;
					}
				}
				
				// check and apply validation if Conversions is our main (anchor) metric
				if(this.anchor === 'conversions'){
					
					if(Number($F(metric)) < Number(this.metrics.get('conversions').getValue())){
						
						//alert('');
						
						metric.value = this.cache.get(metric.kpi);
						
						return false;
					}
				}
			
			break;
			// conversions
			case 'conversions':
			
				// check and apply validation if Clicks is our main (anchor) metic
				if(this.anchor === 'clicks' || this.anchor === 'cpc'){
					
					// essentially we can NOT have more Conversions than we have Clicks; not physically possible
					if(Number($F(metric)) > Number($F(this.metrics.get('clicks')))){
						
						//alert('');
						
						metric.value = this.cache.get(metric.kpi);
						
						return false;
					}
				}
				
			break;
			// cpc
			case 'cpc':
			
			    // check and apply validation if Clicks is our main (anchor) metric
				if(this.anchor === 'clicks'){
					
					// we can NOT alter our CPC since both Clicks and Spend (budget) are anchored; its not physically possible
					if(Number($F(metric)) !== Math.round($F(this.metrics.get('spend_dollars'))/$F(this.metrics.get('clicks')))){
						
						//alert('Error!\r\nYour Clicks are currently fixed at ' + $F(this.metrics.get('clicks')) + '\r\nAs such your CPC cannot be adjusted without changing your Clicks or Spend (Budget)');
						
						metric.value = this.cache.get(metric.kpi);
						
						return false;
					}
				}
			
			break;
			// cost
			case 'spend':
				
				if(Number($F(metric)) > Number(metric.max)){
					
					metric.value = this.cache.get(metric.kpi);
					
					return false;
				}
				
			break;
		}
	},
	
	/**
	 * Finds ALL metrics which are required to succesfully calculate the active metrics value
	 * 
	 * @param {Object} metric
	 * @param {Object} requestingmetric
	 */
	findMetrics:function(metric, requestingmetric){
								
		// regex pattern for extracting metrics
		var __regex = /([a-zA-Z_]+)/g
					
		// check for metric equation
		if(Object.isUndefined(KeyPerformanceIndicatorAlgorithms[metric.kpi].equation) === false){
            
            return KeyPerformanceIndicatorAlgorithms[metric.kpi].equation.match(__regex);
        }
		// check for metric equation based on requesting metric
		// some metrics calculate differently depending on which other metric has called for an update
        else if(Object.isUndefined(KeyPerformanceIndicatorAlgorithms[metric.kpi].equations[requestingmetric.kpi]) === false){
                     
			return KeyPerformanceIndicatorAlgorithms[metric.kpi].equations[requestingmetric.kpi].match(__regex);
        }
	},
	
	/**
	 * Calculates the active metrics new value according to remaining metrics
	 * 
	 * @param {Object} metric
	 * @param {Object} requestingmetric
	 * @param {Object} values
	 */
	calculateMetricValue:function(metric, requestingmetric, values){

		// check for metric equation
		if(Object.isUndefined(KeyPerformanceIndicatorAlgorithms[metric.kpi].equation) === false){
			
			// switch calculation method based on rounding of decimals
			switch(KeyPerformanceIndicatorAlgorithms[metric.kpi].decimals){
                
                case 0: 
                
                	// parse and evaluate equation
                	return Math.round(eval(KeyPerformanceIndicatorAlgorithms[metric.kpi].equation.interpolate(values)));
                
                break;
                case 2: 
            
                    // parse and evaluate equation
                	return Math.round(eval(KeyPerformanceIndicatorAlgorithms[metric.kpi].equation.interpolate(values))*100)/100;
                
                break;
            }
		}
		// check for metric equation based on requesting metric
		else if(Object.isUndefined(KeyPerformanceIndicatorAlgorithms[metric.kpi].equations[requestingmetric.kpi]) === false){
										
			// parse and evaluate equation
			return Math.round(eval(KeyPerformanceIndicatorAlgorithms[metric.kpi].equations[requestingmetric.kpi].interpolate(values)));
		}
	},
	
	/**
	 * Primary method responsible for binding ALL metric input fields (form elements) to the appropriate class methods
	 * 
	 * @param {Object} input
	 */
	bindInputs:function(input){
		
		// check for textbox input
		if((input.type == 'text' && input.hasAttribute('kpi')) || (input.type == 'hidden' && input.id == 'KeyPerformanceIndicator/monthly_budget')){
			
			// bind update method to onBlur action of element
			Event.observe(input, 'blur', this.update.bind(this));
        
            // extract and assign metric dependants and dependencies
			input.dependants = $w(input.getAttribute('dependants'));
            input.dependencies = $w(input.getAttribute('dependencies'));
            			
			// store metric reference
			input.kpi = input.getAttribute('kpi');
			input.id = input.getAttribute('kpi');
			input.max = input.getAttribute('maxlimit');
			input.min = input.getAttribute('minlimit');
			
			// automatically assign our Spend (budget) as an anchor
            input.anchor = (input.kpi == 'spend' ? true : false);
            // CTR and CVR are allowed to have a zero value
			input.allowzero = ($w('ctr cvr conversions').indexOf(input.kpi) == -1 ? false : true);
			
			// store metric information
			this.metrics.set(input.kpi, input);
			this.cache.set(input.kpi, $F(input));
		}
		// check for radio input; the anchor selectors
		else if(input.type == 'radio'){
			
			// bind anchor update method to onClick action of element
			Event.observe(input, 'click', this.updateAnchor.bind(this));
			
			if(input.checked === true){
				
				__targetMetric = input.getAttribute('target');
				
				this.anchor = __targetMetric;
				
				this.metrics.get(__targetMetric).anchor = true;
			}
		}
		// check for checkbox input; the freeform mode switch
		else if(input.type == 'checkbox' && input.id == 'switchFreeForm'){
			
			// bind mode update method to onClick action of element
			Event.observe(input, 'click', this.updateMode.bind(this));
		}
		// check for button input; campaign assignment
		else if(input.type == 'button' && ($w('assign unassign').indexOf(input.id) >= 0)){
			
			if(input.id == 'assign'){
				
				Event.observe(input, 'click', this.assignCampaign.bind(this));
			}
			
			if(input.id == 'unassign'){
				
				Event.observe(input, 'click', this.unassignCampaign.bind(this));
			}
		}
		else if((input.type == 'select-multiple' || input.type == 'select') && ($w('available assigned').indexOf(input.id) >= 0)){
			
			if(input.id == 'available'){
				
				this.availableCampaigns = $(input.id);
			}
			
			if(input.id == 'assigned'){
				
				this.assignedCampaigns = $(input.id);
			}
		}
	},
	
	/**
	 * Switches the portfolio from using real-world logic (cascading metrics) to static/independant calculations
	 * 
	 * @param {Object} event
	 */
	updateMode:function(event){
		
		// return triggering events Object
		input = event.element();
		
		// make sure Object is valid
		if(Object.isUndefined(input) === false){
			
			// switch portfolio mode
			this.freeform = input.checked;
			
			// check if freeform is active
			if(this.freeform === false){
				
				// switching back to real-world logic; re-calculate metrics using Spend (budget) as our reference
				this.updateMetric(this.metrics.get('spend'));
			}
		}
	},
	
	/**
	 * Switches the portfolios main (anchor) metric; from which ALL other metrics will be calculate as required
	 * 
	 * @param {Object} event
	 */
	updateAnchor:function(event){
		
		// return trigger events Object
		anchor = event.element();
		
		// make sure Object is valid
		if(Object.isUndefined(anchor) === false){
			
			// iterate through our portfolios metrics
			this.metrics.each(function(metric){
				
				// check if metric is our current anchor; ignore Spend (budget) as it MUST be anchored
				if(metric[1].anchor === true && metric[0] != 'spend'){
					
					// remove anchoring
					metric[1].anchor = false;
				}
				
				// check if metric is the target of our triggering Object
				if(metric[0] == anchor.getAttribute('target')){
					
					// assign new anchor
					this.anchor = metric[0];
					
					// flag metric as an anchor
					metric[1].anchor = true;
				}
				
			}, this);
		}
	},
	
	assignCampaign:function(event){
		
		for(var i=0; i<this.availableCampaigns.options.length; i++)
    	{
    		if(this.availableCampaigns.options[i].selected)
    		{
    			//source.options[source.selectedIndex].style.display = 'none';
    			this.availableCampaigns.options[i].style.display = 'none';
    			
    			this.assignedCampaigns.options[this.assignedCampaigns.options.length] = new Option(this.availableCampaigns.options[i].text, this.availableCampaigns.options[i].value);
    		}
    	}
	},
	
	unassignCampaign:function(){
		
		for(var i=0; i<this.assignedCampaigns.options.length; i++)
    	{
    		if(this.assignedCampaigns.options[i].selected)
    		{
    			$(this.assignedCampaigns.options[i].value).style.display = 'block';
    		}
    	}	
    	
    	for(var j=0; j<this.assignedCampaigns.options.length; j++)
    	{
			if(this.assignedCampaigns.options[j].selected)
			{
				this.assignedCampaigns.options[j] = null;
				
				j--;
			}
    	}
	},
	
	save:function(event){
		
		control = event.element();
			
		if(this.beforeSave(control) === false) return;
		
		new Ajax.Request('/key_performance_indicators/save_advanced/', {onSuccess:this.afterSave.bind(this), parameters:Form.serialize(this.form), evalJSON:true});
	},
	
	remove:function(event){

		control = event.element();
		
		if(confirm('Delete this portfolio?')){
			new Ajax.Request('/key_performance_indicators/remove/' + this.form['KeyPerformanceIndicatorId'].value, {onSuccess:this.afterRemove.bind(this)});
		}
	},
	
	beforeSave:function(control){
	
		$('KeyPerformanceIndicatorAftersave').value = control.getAttribute('postaction');
		//$('KeyPerformanceIndicator/archive').value = 0;
		
		// check for date difference; anything a week or more in age should suggest archiving
		/*if(DC.dateDiff(DC.date, date(), 'D') >= 7){
			
			if(confirm("This portfolio was last saved (updated) over a week ago. We recommend archiving those values for historic purposes\r\nDo you wish to archive your previous KPIs now ?")){
				
				$('KeyPerformanceIndicator/archive').value = 1;
			}
		}*/
		
		if(this.assignedCampaigns != null){
			
			this.assignedCampaigns.childElements().each(function(child){ child.selected = true; });
		}
		
		return true;
	},
	
	afterSave:function(){
		
		jsonResponse = arguments[0].getHeader('JSON').evalJSON();

		// check for errors on save
		if(jsonResponse.error){
			
			$('notification').update(new Element('li').update(jsonResponse.error)).toggleClassName('panel-errors').show();
			
			return;
		}
		
		if(jsonResponse.message && jsonResponse.aftersave !== 'close'){
			
			$('notification').update(new Element('li').update(jsonResponse.message)).toggleClassName('panel-confirmed').show();
		}

		// check if we are closing after save
		if(jsonResponse.aftersave == 'close'){

			// close popup and reload page
			DC.enableInput(true);
		}
		
		// check for ID
		if(Object.isNumber(jsonResponse.id)){
			
			$('KeyPerformanceIndicator/id').value = jsonResponse.id;
		}
	},
	
	afterRemove:function(){
		// close popup and reload page
		DC.enableInput(true);
	}

});
