/** 
* @projectDescription	Wizard-specific javascript
*
* @id	wizard.js
*/

var WizardSlide = Class.create({
	initialize: function (container) {
		this.container = $(container);		
		this.buttons = this.container.select('.navigation li a');
		this.slider = this.container.down('.slides');
		this.slides = this.slider.select('.step');
		this.slideCount = this.slides.length;
		this.offset = this.slider.positionedOffset()[0];
		this.width = this.slides[0].getWidth();
		this.current = 0;	
		this.madeIt = this.slides.map(function (s) { return false; });
		this.setup();
	},
	setup: function () {
		this.buttons.invoke('addClassName', 'disabled');
		this.buttons[0].removeClassName('disabled').addClassName('active');
		this.buttons.each(function (el, idx) {
			el.observe('click', function (ev) {
				ev.stop();
				this.go(idx);
			}.bind(this));
		}.bind(this));
		this.lockTabs();
		this.madeIt[0] = true;
		document.observe('wizard:results', this.toResults.bind(this));
		document.observe('wizard:next', this.next.bind(this));
		document.observe('wizard:previous', this.prev.bind(this));
		document.observe('wizard:unlock', this.unlock.bind(this));
		document.observe('wizard:start', function(){
			this.go(0); 
			this.lockTabs();
		}.bind(this));
		document.observe('wizard:lockresults', function(ev){this.resultLock(ev.memo.lock)}.bind(this))
		document.observe('wizard:resetheight', this.reset_height.bind(this));
	},
	lockTabs: function(){
		this.locks = this.buttons.map(function(b){return true});
		this.locks[0] = false;
		//this.locks[this.slideCount-1] = false;
		this.buttons.invoke('addClassName', 'disabled');
		this.buttons.invoke('removeClassName', 'complete');
		this.buttons[0].removeClassName('disabled').addClassName('active');
		this.container.select('.next').invoke('addClassName','disabled');
	},
	go: function (idx) {
		if (this.locks[idx]) return;
		if (idx < 0 || idx >= this.slideCount) { 
			return;
		}

		this.current = idx;
		
		//Omniture
		if (!this.madeIt[this.current]) {
			Omniture.trackIncWizard(this.current);
		}
		
		this.madeIt[this.current] = true;

		this.buttons.invoke('removeClassName', 'active');
		this.buttons[idx].addClassName('active');
		
		if (this.moving) {
			this.moving.cancel();
		}
		
		this.moving = new Effect.Move(this.slider, {
			mode: 'absolute', 
			x:(-(idx * this.width) + this.offset), 
			duration: 0.7, 
			transition:Effect.Transitions.EaseFromTo,
			afterFinish: function() {
				this.grow(this.slides[idx]);				
			}.bind(this)
		});
	},
	unlock: function(){
		this.locks[this.current + 1] = false;
		this.buttons[this.current].addClassName('complete');
		this.buttons[this.current + 1].removeClassName('disabled');
		this.slides[this.current].down('.next, .results').removeClassName('disabled');
	},
	grow: function (slide) {
		var overflow = this.container.down('.overflow');
		var module = this.container.down('.column_b');
		if (this.growing) { 
			this.growing.cancel();
		}
		if (this.scrolling) {
			this.scrolling.cancel();
		}	
		this.growing = new Effect.Morph(overflow, {
			style: 'height:' + slide.getHeight() + 'px;',
			transition:Effect.Transitions.EaseFromTo,
			duration: 0.6,
			afterFinish: function () {

				this.scrolling = new Effect.ScrollTo($('container'), {
					transition:Effect.Transitions.EaseFromTo,
					duration: 0.6
				});

			}.bind(this)
		});
		this.growing2 = new Effect.Morph(module, {
			style: 'height:' + slide.getHeight() + 'px;',
			transition:Effect.Transitions.EaseFromTo,
			duration: 0.6
		});
	},
	reset_height: function(){
	    this.grow(this.slides[this.current]);
	},
	next: function (ev){
		this.go(this.current + 1);
		
		if (ev) {
			ev.stop();
		}
	},
	prev: function (ev){	
		this.go(this.current - 1);
		if (ev) {
			ev.stop();
		}
	},
	toResults: function(ev){
		this.go(this.slideCount-1);
	},
	resultLock: function(lock){
	    this.locks[this.slideCount-1] = lock;
	}
});

/*--------------------------------------------------------------------------*/

var WizardMeter = Class.create({
	initialize: function (container) {
		this.container = $(container);
		this.barSet = this.container.down('.bars');
		this.bars = this.container.select('.bar');
		this.meters = this.container.select('.meter');
		this.setup();
	},
	setup: function () {
		this.barSet.observe('mouseleave', function () {
			this.bars.invoke('removeClassName', 'hover');
		}.bind(this));
		this.bars.each(function (el, i) { 
			el.observe('mouseenter', this.highlight.bind(this, i));
		}.bind(this));
		this.meters.each(function (el, i) {
			this.timeout = setTimeout(function () {
				this.decrease(el, 0);
			}.bind(this), 120 * i);
		}.bind(this));
		
		document.observe('wizard:start', function() {
			this.bars.invoke('removeClassName', 'inactive');
		}.bind(this));
	},
	decrease: function (meter, amount) {
		new Effect.Morph(meter, {
			style: 'width:' + amount + '%;',
			duration: 1.7,
			transition: Effect.Transitions.EaseFromTo,
			afterFinish: function () {
				//meter.up('.bar').addClassName('inactive');
			}.bind(this)
		});
	},
	highlight: function (idx) {
		this.bars.invoke('removeClassName', 'hover');
		this.bars[idx].addClassName('hover');
	}
});

/*--------------------------------------------------------------------------*/

var ScoreKeeper = Class.create({
	initialize: function(container, meter_sel,startover, answers, data){
		this.container = container;
		this.totals = {};
		this.data = data;
		this.scores = {};
        this.init_values();
        this.meter_sel = meter_sel;
        this.startover_btn = startover;
        this.done_through = 1;
        this.setup();
        this.answers = answers;
        this.container.reset();
        this.disableResults();
        this.stop_snap_after = data.STOP_SNAP_AFTER || 0;
        this.num_answered = 0;
        this.fresh = true;
        this.exclusion_groups = {};
        this.reasons = new Hash();
        this.disqualify_pop = $('disqualification_tooltip');
        this.disqualify_pop.down('.close').observe('click', function(ev){
            this.disqualify_pop.hide();
            document.stopObserving('click'); 
        }.bind(this));
        this.data.PRODUCTS.each(function(p){
			this.reasons.set(p, new Hash());
        }.bind(this));
        document.observe('reasons:showdetails', this.show_reason_details.bind(this));
	},
	reset: function(){
		this.data.PRODUCTS.each(function(p){
			this.scores[p] = 0;
		}.bind(this));
	},
	init_values: function(){
		this.data.PRODUCTS.each(function(p){
			var vals = Object.values(this.data.WEIGHTS).pluck(p);
			this.totals[p] = 0;
			this.scores[p] = 0;
			vals.reject(function(v){return typeof(v)=='string'}).each(function(val){
				this.totals[p] += val;
			}.bind(this));
		}.bind(this));
	},
	setup: function(){
		this.inputs = this.container.getInputs().invoke('observe', 'click', this.calculate.bind(this));
		this.meters = {};
		$$(this.meter_sel).each(function(el){
		    var id = el.id.split('_')[0];
			this.meters[id] = el;
			el.previous('a').observe('click', this.show_reason.bind(this, id, el.up('.bar')));
		}.bind(this));
		this.startover_btn.observe('click', this.startover.bind(this));
		
		$$('.resultlink').invoke('observe','click', this.results.bind(this));
        $$('.next').invoke('observe','click', function(ev){ev.stop(); document.fire('wizard:next');}.bind(this));
        $$('.prev').invoke('observe','click', function(ev){ev.stop(); document.fire('wizard:previous');}.bind(this));
	},
	show_reason: function(prod, el, ev){
	    if (el.hasClassName('inactive')){
    	    ev.stop();
	        var r = this.reasons.get(prod);
	        var reasons = this.build_reason_items(r);
	        var out = PRODUCT_REASON_TEMPLATE.evaluate({product:this.get_prod_display(prod),
	                                                    reasons: reasons,
	                                                    intro: this.data.DISQUALIFY_INTRO[prod],
	                                                    url:ev.element().up('a').readAttribute('href')});
	                                                    
	        this.disqualify_pop.writeAttribute('class', 'tooltip '+prod)
	        .down('#disqualification_tooltip_content').update(out);
	        this.show_disqualify_pop(); 
	    }
	},
	show_disqualify_pop: function(){
       this.disqualify_pop.show();
	   document.observe('click', function(ev){
	       if (! ev.element().up('#disqualification_tooltip')){
    	       this.disqualify_pop.hide();
    	       document.stopObserving('click');    
	       }
	   }.bind(this));
	},
	build_reason_page: function(){
	    var out = '';
	    this.reasons.keys().each(function(k){
	        var r = this.reasons.get(k);
	        if (r.size() == 0) return;
	        var reasons = this.build_reason_items(r);
	        out += REASON_TEMPLATE.evaluate({product:this.get_prod_display(k), reasons:reasons, intro:this.data.DISQUALIFY_INTRO[k]})
	    }.bind(this));
	    var page = this.toggle_reason_page(true);
	    page.down('.generated').update(out);
	},
	show_reason_details: function(){
	    this.container.down('#noresult_details').show();
	    document.fire('wizard:resetheight');
	    
	},
	toggle_reason_page: function(on){
	    if (on)
	       this.container.select('.desc').invoke('hide');
	    this.container.down('div.step.results').removeClassName('tie').addClassName('noresult');
	    return this.container.down('.desc.noresult')[on?'show':'hide']();
	    
	},
	build_reason_items: function(r){
	    return r.values().map(function(r){return REASON_ITEM_TEMPLATE.evaluate({reason:r})}).join('');
	},
	startover: function(ev){
		this.container.reset();
		this.calculate();
		document.fire('wizard:start');
		ev.stop();
		this.disableResults();
		this.fresh = true;
		
		//Omniture
		Omniture.trackIncWizardRestart();
	},
	check_exclusions: function(inp){
        var group = inp.value.match(/\D+\d+/);
        var checked = inp.checked;
	    var weights = this.data.WEIGHTS[inp.value];
	    if ($H(weights).keys().include('exclusive')){
	       if(checked){
    	       inp.up('.inner').select('input').each(function(el){
                    if (inp != el) el.checked='';
                });
           this.exclusion_groups[group]=inp;     
           } else{
            delete this.exclusion_groups[group];                
           }
	    }else{
	        if (checked){
	            if (this.exclusion_groups[group]){
	               var inp = this.exclusion_groups[group];
	               inp.checked='';
	               delete this.exclusion_groups[group];
	            }
	        }
	    }
	    
	},
	calculate: function(ev){
	    if (ev)
	       this.check_exclusions(ev.element());
		this.reset();
		this.inputs.each(function(inp){
			if (! inp.checked) return;
            var weights = this.data.WEIGHTS[inp.value];
            var group = inp.value.match(/\D+\d+/);
            
            this.data.PRODUCTS.each(function(prod){
            	var score = weights[prod];
            	
            	if (typeof(score)=='string'){
            	   this.reasons.get(prod).set(group,  this.data.DISQUALIFIERS[inp.value+'.'+prod]);
            	   this.scores[prod] = score;
            	}
            	else{
            	   this.reasons.get(prod).unset(group);
            	   this.scores[prod]+=weights[prod];
            	}
            }.bind(this));			
		}.bind(this));
		var valid = false;
		this.data.PRODUCTS.each(function(p){
			if (this.set_status(p, this.scores[p]))
    			valid = true;
		}.bind(this));

		
		if (valid){
		    this.noresults=false;
    		if (ev){
    			var done = true;
    			var page = ev.element().up('.questions').select('.question');
    			page.each(function(q){
    				if (q.select('input').findAll(function(i){return i.checked;}).length==0){
    	                 done=false;
    				}
    			});
    			if (done){
    			     document.fire('wizard:unlock');
    			}
    		}
    		this.enableResults();
		    this.answers.removeClassName('disqualified');
		    this.container.down('div.step.results').removeClassName('noresult')
		    $('disqualification_error').hide();
		}
        else{ // ALL ANSWERS INVALID!
            this.noresults=true;
            this.disableResults();
            this.answers.addClassName('disqualified');
    	    var e = ev.element().up('.question').insert({after:$('disqualification_error').hide().slideDown({
    	        afterFinish:function(){
            	    document.fire('wizard:resetheight');
    	        }
    	    })});
    	    this.build_reason_page();
    	    e.next().down('a').observe('click', function(ev){
        	    document.fire('wizard:results');
    	    }.bind(this));
        }
		
		if (this.fresh){
		    this.enableResults();
		    this.fresh = false;
		}
	   this.num_answered = $H(Form.serialize(this.container, true)).keys().size();
	},
	disableResults: function(){
        //document.fire('wizard:lockresults', {lock:true})
        $$(':not(li)>a.resultlink').invoke('hide');
	},
	enableResults: function(){
 	    document.fire('wizard:lockresults', {lock:false})
		$$(':not(li)>a.resultlink').invoke('show');
	},
	set_status: function(type, val){
		var meter = this.meters[type];
		var valid = true;
		if (typeof(val)=='string'){
		  val = 0;
          meter.up('.bar').addClassName('inactive');
          valid = false;
		}else{
		  meter.up('.bar').removeClassName('inactive');
		}
		var percent = this.prod_score(type, val);
		
		if (this.stop_snap_after && (this.num_answered < this.stop_snap_after)){
		      percent = Math.round(percent/5)*5;
		}
		
		new Effect.Morph(meter, {
			style:{ width:percent+'%'},
			transition: Effect.Transitions.EaseFromTo,
			duration: 0.6
		});
		return valid;
	},
	results: function(ev){
		if (! this.noresults){
    		var winners = this.get_winner();
			
			//Omniture
			Omniture.trackIncWizardResult(winners[0]);
			
    		var tie = winners.length > 1;
    		if (tie)
    		  $('winner').update(winners.map(function(s){return this.get_prod_display(s, true);}.bind(this)).join(' or '));
    		else
    		  $('winner').update(this.get_prod_display(winners[0], true));
    		$$('.step.results')[0][tie ?'addClassName':'removeClassName']('tie');
    		winners = winners.map(function(s){return '.desc.'+s}).join(',');
    		$$('.desc').invoke('hide');
    		$$(winners).invoke('show');
		}
		document.fire('wizard:results');
		ev.stop();
	},
	get_prod_display: function(prod, with_prefix){
	    var ind = this.data.PRODUCTS.indexOf(prod);
	    if (with_prefix)
	       return this.data.PRODUCT_DISPLAY_PREFIX[ind] + ' <strong>'+this.data.PRODUCT_DISPLAY[ind]+'</strong>';
        else
           return this.data.PRODUCT_DISPLAY[ind];	       
	},
	prod_score: function(prod, val){
		if (typeof(val)=="string") return 0;
		var tot = this.data.MAX_POINTS[this.data.PRODUCTS.indexOf(prod)];
		return (val/tot)*100;
	},
	get_winner: function(){
		var scorelist = [];
		$H(this.scores).each(function(pair){scorelist.push({product:pair.key,score:this.prod_score(pair.key, pair.value)});}.bind(this));
		scorelist = scorelist.sortBy(function(v){return v.score}).reverse();
		if (scorelist[0].score-scorelist[1].score <= this.data.TIE_THRESHOLD){
			return [scorelist[0].product, scorelist[1].product];
		}
		return [scorelist[0].product];
		
	}
});

/*--------------------------------------------------------------------------*/

var REASON_TEMPLATE = new Template("<h4>#{product}</h4><p>#{intro}</p><ul>#{reasons}</ul>");
var REASON_ITEM_TEMPLATE = new Template("<li>#{reason}</li>");
var PRODUCT_REASON_TEMPLATE = new Template('<strong>#{product} Has Been Disqualified</strong> <p>#{intro}</p> <ul>#{reasons}</ul> <div class="ctas"> <p><a class="cta" href="#{url}">View Product Details</a></p> <p><a class="cta" href="/service/contact.aspx">Contact Us with Questions</a></p> </div>');

/*--------------------------------------------------------------------------*/

document.observe('dom:loaded', function () {
	var wizard = $('wizard');
	if (wizard) {
		new WizardSlide(wizard);
		new WizardMeter(wizard);
		new ScoreKeeper($('wizardform'), '.meter', $('resetwizard'), $$('.module_answers')[0], WIZARD_DATA);
	}
});

