allDealers = [];
pagedDealers = {};
currentPage = 1;
customerVehicles = [];

var error_message_no_search_results = "Your search produced no matches. Please revise your search criteria and search again.";
var error_message_not_available = "We are sorry, your request cannot be processed at this time. Please try again later.";


var dealerAttributeUrlMap = $H({
    3: 'http://www.toyota.com/dealers/services/express_lube.html',
    4: 'http://www.toyota.com/dealers/services/parts_center.html',
    5: '#',
    7: '#',
    8: 'http://www.toyota.com/dealers/services/certifie_used_vehicles.html',
    12: 'http://www.toyota.com/dealers/services/tire_center.html'
});

DEALERS_PER_PAGE = 5;



var DealerLocator = {

    getDealerResults: function(url, form, searchType) {
        $("searchType").value = searchType;

        if (this.validateSearchCriteria(form, searchType)) {

            var ajaxRequest = new Ajax.Request(url, {
              method: 'GET',

                parameters: Form.serialize(form),

                onSuccess: function(transport) {
                    var json = transport.responseText.evalJSON();

                    if (json.status == 'SUCCESS') {
                        $('dealer-locator-search-container').fade({
                            duration: .25,
                            from: .25,
                            to: 0,
                            queue: 'start'
                        });

                        $('content').appear({
                            queue: 'end',
                            duration: 0.5
                        });

                        DealerLocator.processResults(transport);
                        DealerListView.insertId(json.dealers);
                        DealerListView.renderResults(json, searchType);


                    } else {
                        if (json.status == "FAILURE") {
                            if (json.error == "NO_RESULTS") {
                            	$('dealer-locator-search-container').show();
                                $('dealer_search_error').update(error_message_no_search_results);
                            } else {
                            	$('dealer-locator-search-container').show();
                                $('dealer_search_error').update(error_message_not_available);
                            }
                        }
                    }
                },

                onException: function(req, exception) {
                    $('content').style.display = '';
                    var json = req.transport.responseText.evalJSON();
                    if (json.status == "FAILURE") {
                        $('tabs-view').style.display = 'none';
                        if (json.error == "NO_RESULTS") {
                        	$('dealer-locator-search-container').show();
                            $('dealer_search_error').update(error_message_no_search_results);
                        } else {
                        	$('dealer-locator-search-container').show();
                            $('dealer_search_error').update(error_message_not_available);
                        }
                    }
                    return true;
                }
            });
        }
    },

    validateSearchCriteria: function(form, searchType) {
        ViewHandler.clearErrors();
		
        if (searchType == "ZIPCODE") {
        	var mask = /^\d{5}$|^\d{5}$/;
			
            if (form.zip.value == null || form.zip.value == "" || form.zip.value == "Enter Zip Code") {
                $('zip_search_error').update('Zip Code is required.');
                return false;
            } else if (!mask.test(form.zip.value)) {
            	$('zip_search_error').update('The zip code you entered is invalid, please enter a valid zip code');
            } else {
                return true;
            }
        } else if (searchType == "CITY_STATE") {
            var hasError = false;
            var cityMask = /^[a-zA-Z0-9\s\-\,\'&amp;]*$/
            
            if (form.city.value == null || form.city.value == "" || form.city.value == "Enter City") {
                $('city_state_search_error').insert({
                    'bottom': Builder.node('p', ['City is required.'])
                });
                hasError = true;
            } else if (!cityMask.test(form.city.value)) {
 				$('city_state_search_error').insert({
                    'bottom': Builder.node('p', ['City has an invalid format.'])
                });            
            	hasError = true;
            }
            
            
            if (form.state.value == null || form.state.value == "") {
                $('city_state_search_error').insert({
                    'bottom': Builder.node('p', ['State is required.'])
                });
                hasError = true;
            }

            if (hasError) {
                return false;
            }
            return true;

        } else if (searchType == "DEALERNAME") {
            if (form.dealerNameField.value == null || form.dealerNameField.value == "" || form.dealerNameField.value == "Enter Dealer Name") {
                $('dealer_name_search_error').insert({
                    'bottom': Builder.node('p', ['Dealer Name is required.'])
                });
                return false;
            }
            return true;
        }
        return false;
    },

    processResults: function(transport) {

        var responseJSON = transport.responseText.evalJSON();

        if (responseJSON != null) {
            if (responseJSON.status == "SUCCESS") {
                var dealerResults = responseJSON.dealers;

                MapView._customerVehicles = responseJSON.vehicles;
                MapView._dealerResults = responseJSON.dealers;
            }
        }
    },
    
    changePreferredDealer: function(dealerCode) {
    	var dealerForm = $('preferredForm' + dealerCode);
    	
    	if (!DealerLocator.confirmPreferredDealer(dealerCode)) {
    		$('preferredFormErrors' + dealerCode).update('Please confirm your selection');
    		$('preferredCheckbox' + dealerCode).highlight();
    		return false;    		
    	}
    	
    	$('preferredFormErrors' + dealerCode).update('Saving your changes...');
    	
    	new Ajax.Request('/Owners/dealer/changeDealer.do', {
    		
    		parameters: dealerForm.serialize(),
    		
    		onSuccess: function(transport) {
    		  var json = transport.responseText.evalJSON();
    		  
    		  if (json.status == 'SUCCESS') {
      			$('preferredForm' + dealerCode).update('Preferred dealer was saved successfully');
      			$('preferredDealerInfo' + dealerCode).update('');
      		} else {
            $('preferredFormErrors' + dealerCode).update('An error occured while saving. Please try again later.');
          }
    		},
    		
    		onFailure: function(transport) {
    		  $('preferredFormErrors' + dealerCode).update('An error occured while saving. Please try again later.');
    		}
    	});
    	
	    return false;	
    },
    
    confirmPreferredDealer: function(dealerCode) {
    	var confirmed = $('confirmPreferred' + dealerCode).checked;
    	
    	return confirmed;
    }
}



var DealerListView = {
    currentPage: function() {
        return currentPage;
    },

    insertId: function(dealers) {
        dealers.each(function(d, index) {
            d.id = index + 1;
        })
    },

    renderResults: function(response, searchType) {
        customerVehicles = response.vehicles || $A();
        allDealers = $A(response.dealers);
        var header = 'We found ' + allDealers.size() + ' Toyota Dealers ' ;
        
        if (searchType == 'ZIPCODE') {
        	header += 'near ' + $('zipField').value;
        } else if(searchType == 'CITY_STATE') {
        	header += 'near ' + $('cityField').value;
        } else {
        	header += 'named ' + $('dealerNameField').value;
        }
        
        $('dealer_search_results_header').update(header);
        
        pagedDealers = DealerListView.reduceDealers(allDealers, DEALERS_PER_PAGE);
        
        DealerListView.renderPageNumbered(1);
    },


    reduceDealers: function(dealers, pageSize) {
        var pagedResults = $H();
        var currentPage = 1;

        var startPointer = 0;
        var endPointer = pageSize - 1;
        var lastItemIndex = dealers.size() - 1;

        if (endPointer > lastItemIndex) {
            pagedResults.set(1, dealers);
        }


        while (endPointer <= lastItemIndex && startPointer <= lastItemIndex) {
            var currentList = $A();

            $R(startPointer, endPointer).each(function(d, index) {
                this[index] = dealers[d];
            },
            currentList);

            pagedResults.set(currentPage, currentList);

            startPointer = endPointer + 1;

            var nextEnd = endPointer + pageSize;

            endPointer = (nextEnd < lastItemIndex) ? nextEnd: lastItemIndex;

            currentPage++;

        }

        return pagedResults;
    },


    buildResultRow: function(dealer, index) {

        var td_first = Builder.node('td', {
            'class': 'first'
        },
        Builder.node('div', {
            'class': 'dealer_pin'
        },
        dealer.id));

        var td_name_address = null;
        var name = Builder.node('a', {
            'href': dealer.uri,
            'class': 'dealer_name'
        },
        dealer.dealerName);
        var address = dealer.address.addressLine1;
        var city = dealer.address.city;
        var state = dealer.address.state;
        var zip = dealer.address.zipCode;
        var phone = '';
        if (dealer.phoneNumber != '') {
          phone = [dealer.phoneNumber, Builder.node('br'), Builder.node('br')];        
        } else {
          phone = Builder.node('br');
        }

        
        
        var hoursArray = DealerDetailView.buildHoursOfOperations(dealer);
        var dealerWebsite = Builder.node('a', {
            'href': dealer.uri,
            'target':'_blank',
            'class':'button'
        },
        Builder.node('span', 'Dealer website'));        
        
        var hours = [];
        
        if(DealerDetailView.hasHoursOfOperations(hoursArray)) {        	
        	hours = Builder.node('a', {
                'href': '#',
                'id': 'hours' + dealer.id + 'link'
            },
            'Hours');

            hours = [hours, Builder.node('div', {
                'id': 'hours' + dealer.id + 'tip',
                'style': 'display:none;',
                'class': 'hoursTip'
            }, 
            hoursArray)];
        }   

        td_name_address = Builder.node('td', [
          name,
          Builder.node('br'),
          address,
          Builder.node('br'),
          city, ', ', state, ' ', zip,
          Builder.node('br'),
          phone,
          dealerWebsite,
          Builder.node('br'),
          Builder.node('br'),
          hours
        ]);

		    var miles = (dealer.proximity == 'null') ?  '' : [dealer.proximity + ' miles away', Builder.node('br')];

        var td_map_distance = Builder.node('td', [
        miles,
        Builder.node('a', {
            'href': '#',
            'onclick': 'MapView.showMapFromListPage(' + dealer.id + '); return false'
        },
        'Map & Driving Directions')
        ]);

        var td_attributes = null;
        var ul_attributes = null;
        var li_collection = new Array();
        dealer.dealerAttributes.each(function(a) {
            li_collection.push(Builder.node('li', a.dealerAttributeName));
        });
        ul_attributes = Builder.node('ul', li_collection);
        td_attributes = Builder.node('td', ul_attributes);


        var td_contact = null;
        var appointment;
        if (dealer.financeURL != '') {  
          var button = Builder.node('span', 'Schedule Appointment');
        
          appointment = Builder.node('a', {
              'href': dealer.financeURL,
              'target':'_blank',
              'class':'button'
          }, [button, Builder.node('br')]);
        }
        
        var certifiedSearch = Builder.node('a', {
            'href': DealerListView.certifiedUrl(dealer),
            'target':'_blank'
        },
        'Search Certified Used Inventory');
        
        /*
        var dealerWebsite = Builder.node('a', {
            'href': dealer.uri,
            'target':'_blank'
        },
        'Dealer website');
        */
        
        var dealerDetails = Builder.node('a', {
            'href': '#',
            'onclick': 'DealerDetailView.renderSideBar(' + dealer.id + '); return false'
        },
        'Dealer Details');
        
        var preferredDealer;
        
        preferredDealer = PreferredDealer.preferredContainer(dealer.dealerCode, customerVehicles.size());
            

		var dealerCoupons = DealerDetailView.buildDealerCoupons(dealer);		

		td_contact = Builder.node('td', [
			appointment,
			certifiedSearch,
			Builder.node('br'),
			dealerCoupons,
			dealerDetails,
			Builder.node('br'),
			preferredDealer
		]);
            

        var odd_or_even = (index % 2 != 0) ? 'row_even': 'row_odd';

        var tr_row = Builder.node('tr', {
            'class': odd_or_even
        },
        [td_first, td_name_address, td_map_distance, td_attributes, td_contact]);

        return tr_row;
    },

    paginationFooter: function(numberOfPages, currentPage) {
        var arrows = $A();
        if (currentPage == 1) {
        	if (allDealers.size() > 1 && allDealers.size() > DEALERS_PER_PAGE) {
	        	arrows[0] = Builder.node('a', {
				        		'href':'#',
				        		'class':'next_page',
				        		'onclick':'DealerListView.renderPageNumbered(' + (currentPage + 1) + '); return false;'
	       		});
       		}    		 
        } else if (currentPage == numberOfPages) {
        	arrows[0] = Builder.node('a', {
			        		'href':'#',
			        		'class':'previous_page',
			        		'onclick':'DealerListView.renderPageNumbered(' + (currentPage + - 1) + '); return false;'
       		});        	
        } else {
        	arrows[0] = Builder.node('a', {
			        		'href':'#',
			        		'class':'previous_page',
			        		'onclick':'DealerListView.renderPageNumbered(' + (currentPage - 1) + '); return false;'
       		});
       		
        	arrows[1] = Builder.node('a', {
			        		'href':'#',
			        		'class':'next_page',
			        		'onclick':'DealerListView.renderPageNumbered(' + (currentPage + 1) + '); return false;'
       		});        		        
        }
		
		var footer = $('pagination-footer');
        footer.update('');
        
        arrows.each(function(a) {
        	footer.insert({'bottom':a});
        });
        
        var text = 'NAMED ' + pagedDealers.get(currentPage).first().id + '-' + pagedDealers.get(currentPage).last().id + ' of ' + allDealers.size();
        
        footer.insert({'bottom':text});
    },

    renderPageNumbered: function(pageNumber) {
        pageNumber = pageNumber || currentPage;

        // clear out previous search results
        var resultsTBody = $('dealer_list_content');
        resultsTBody.update('');

        pagedDealers.get(pageNumber).each(function(d, index) {
            resultsTBody.insert({
                'bottom': DealerListView.buildResultRow(d, index)
            });
            
            var tip1 = $('hours' + d.id + 'link');
            var tip2 = $('hours' + d.id + 'tip');
            if (tip1 != null) {
                new Tooltip('hours' + d.id + 'link', 'hours' + d.id + 'tip', {
                    delta_x: -250,
                    delta_y: -250
                });
            }
            
            $$('select.vehiclesList').each(function(s) {
              s.getElementsByTagName('option')[0].selected = true;
            });
        });

        DealerListView.paginationFooter(pagedDealers.size(), pageNumber);

        // MapView.renderResults(pagedDealers.get(pageNumber));

        currentPage = pageNumber;
    },


    certifiedUrl: function(dealer) {
        var base = 'http://www.toyotacertified.com/inventory/index.html?language=E';
        base += '&SearchDealerCode=' + dealer.dealerCode;
        return base;
    }
}


var MapView = {

    _dealerResults: null,
    _dealermap: null,
    _dealerPoints: null,
    _lastRoute: null,
    _customerVehicles: null,

    renderResults: function(dealers) {
        $('dealer-accordion-container').update('');
		
        dealers.each(function(d, index) {
            var dealerMapListing;
            var dealerPin = Builder.node('div', {
                'class': 'dealer_pin'
            },
            d.id);
            
            
            var header = Builder.node('a', {
                'class': 'header',
                'onclick': 'MapView.toggleDetailBlock(' + d.id + ')'
            },
            d.dealerName);
            
            
            var listingDetails = Builder.node('div', {
                'id': 'listing' + d.id,
                'class': 'dealer_info_detail listing-closed'
            },
            MapView.buildDetailBlock(d));


            var dealerInfo = Builder.node('div', {
                'class': 'dealer_info'
            },
            [header, listingDetails, Builder.node('div', {
                'class': 'clear'
            })]);


            dealerMapListing = Builder.node('div', {
                'class': 'dealer_map_listing',
                'id': 'dealer-map-listing' + d.id
            },
            [dealerPin, header, dealerInfo]);


            $('dealer-accordion-container').insert({
                'bottom': dealerMapListing
            });
        });

		  var footer = MapView.paginationFooter(dealers);
		
		  $('dealer-accordion-container').insert({
        'bottom':footer
      });
    },


    paginationFooter: function(dealers) {
    var arrows = $A();

        if (currentPage == 1) {
          if (allDealers.size() > 1 && allDealers.size() > DEALERS_PER_PAGE) {
            arrows[0] = Builder.node('a', {
                    'href':'#',
                    'class':'next_page',
                    'onclick':'MapView.renderPageNumbered(' + (currentPage + 1) + '); return false;'
            });
          }
        } else if (currentPage == pagedDealers.keys().size()) {
        	arrows[0] = Builder.node('a', {
                  'href':'#',
                  'class':'previous_page',
                  'onclick':'MapView.renderPageNumbered(' + (currentPage + - 1) + '); return false;'
       		});        	
        } else {
        	arrows[0] = Builder.node('a', {
                  'href':'#',
                  'class':'previous_page',
                  'onclick':'MapView.renderPageNumbered(' + (currentPage - 1) + '); return false;'
       		});
       		
        	arrows[1] = Builder.node('a', {
                  'href':'#',
                  'class':'next_page',
                  'onclick':'MapView.renderPageNumbered(' + (currentPage + 1) + '); return false;'
          });
        }

        var text = 'NAMED ' + dealers.first().id + '-' + dealers.last().id + ' of ' + allDealers.size();

    var footer = Builder.node('div', {
      'class': 'dealer_map_listing',
      'style': 'padding-top: 6px; padding-bottom: 6px;'
    }, [arrows, text]);	

        return footer;
    },

    buildDetailBlock: function(dealer) {
		var dealerCoupons = DealerDetailView.buildDealerCoupons(dealer);		
    
        return [
        dealer.address.addressLine1,
        Builder.node('br'),
        dealer.address.city,
        ', ',
        dealer.address.state,
        ' ',
        dealer.address.zipCode,
        Builder.node('br'),
        dealer.phoneNumber,
        Builder.node('br'),
        Builder.node('br'),
        MapView.buildDrivingDirectionsBlock(dealer),
        Builder.node('br'),
        Builder.node('br'),
        Builder.node('a', {
            'href': '#',
            'onclick': 'DealerDetailView.renderSideBar(' + dealer.id + '); return false'
        },
        'Dealership Details'),
        Builder.node('br'),
        Builder.node('a', {
            'href': DealerListView.certifiedUrl(dealer)
        },
        'Search Certified Used Inventory'),
        Builder.node('br'),
        Builder.node('a', {
            'href': dealer.uri,
            'target':'_blank'
        },
        'Dealer website'),
        dealerCoupons
        ];
    },

    showDetailBlock: function(id) {
        $('listing' + id).removeClassName('listing-closed');
    },

    hideDetailBlocks: function() {

        $$('div.dealer_info_detail').each(function(f) {
            if (!f.hasClassName('listing-closed')) {
                f.addClassName('listing-closed');
            }
        });
    },

    toggleDetailBlock: function(id) {
        MapView.hideDetailBlocks();
        MapView.showDetailBlock(id);
    },

    showMapFromListPage: function(id) {

        ViewHandler.toggleTabs({
            'show': ['map-and-dealer-detail-view-container', 'map-container', 'dealer_map_listings'],
            'hide': ['dealer_view'],
            'show_btn': 'map_button',
            'hide_btn': 'list_button'
        });

		MapView.renderPageNumbered(currentPage);
        MapView.toggleDetailBlock(id);

        return false;
    },
    
    renderPageNumbered: function(pageNumber) {
    	currentPage = pageNumber; 	
		MapView.renderResults(pagedDealers.get(currentPage));
        MapView.displayDealerMap(pagedDealers.get(currentPage));    
    },
    

    buildSelectPreferredDealerBlock: function() {
        if (this._customerVehicles != null) {


            }

    },

    getDrivingDirectionsFromForm: function(form, dealerCode) {
        //var formName = "getDirectionsToDealerForm_" + dealerCode;
        //var form = $(formName);
        //alert("start address: " + form.startAddress.value + " | end address:" + form.endAddress.value);
        this.getDrivingDirections(form.startAddress.value, form.endAddress.value, dealerCode, false);
    },

    getDrivingDirections: function(startAddress, endAddress, dealerCode, reverseDirection) {

        //this.clearMap();

        var thisRoute = {
            start: startAddress,
            end: endAddress,
            idx: 1,
            reverse: reverseDirection,
            dealerCode: dealerCode
        };
        //f.idx.value
        this._lastRoute = thisRoute;


        //check if there are any current directions on page and remove the div
        /*
        var removeTurnList = $("dealer_map_turn_list_current");
        if (removeTurnList != null && removeTurnList.parentNode != null) {
            var removeTurnListParentNode = removeTurnList.parentNode;
            removeTurnListParentNode.removeChild(removeTurnList);
        }
        //var removeTurnListAfter = $("dealer_map_turn_list_current");
        //create the current div to put in driving directions.
        var mapTurnListDiv = $("dealer_map_turn_list_" + dealerCode);
        var mapTurnListCurrentDiv = Builder.node('div', {
            'id': 'dealer_map_turn_list_current'
        });
        $("dealer_map_turn_list_" + dealerCode).insert({
            'bottom': mapTurnListCurrentDiv
        });
        */

        if (typeof this._lastRoute == "object") {

            var options = new VERouteOptions;
            options.DrawRoute = true;
            options.RouteCallback = this.writeDrivingDirections;
            options.DistanceUnit = VERouteDistanceUnit.Mile;
            options.UseMWS = true;

            if (this._lastRoute.reverse) {
                locations = new Array(this._lastRoute.end, this._lastRoute.start);
            } else {
                locations = new Array(this._lastRoute.start, this._lastRoute.end);
            }

            if (this._dealermap != null) {
                this._dealermap.GetDirections(locations, options);
            } else {
                //alert("this._dealermap is null");
            }
        }
        return false;

    },

    writeDrivingDirections: function(route) {
        /* MapPoint takes over scope, so let's use a shortcut for the dealerlocate object */
        if (route) {
            /* build driving directions text */
            var directions = "<table id='directions-table'>";
            var legs = route.RouteLegs;
            for (k = 0; k < legs.length; k++) {
                leg = legs[k];
                for (i = 0; i < leg.Itinerary.Items.length; i++) {
                    directions += "<tr><td class='direction_listing_cell'>";
                    if (i === 0) {                    	
                        directions += "<span class='directions_start'>&nbsp;</span></td><td class='direction_terminus_listing_cell'>";
                    } else if (i == (leg.Itinerary.Items.length - 1)) {
                        if (MapView._lastRoute.reverse) {
                            directions += "<span class='directions_start'>&nbsp;</span></td><td class='direction_terminus_listing_cell'>";
                        } else {
                            directions += "</td><td class='direction_listing_terminus_cell'>";
                        }
                    } else {
                        directions += "<span class='directions_numbers'>" + (i) + "</span></td><td class='direction_listing_cell'>";
                    }
                    directions += leg.Itinerary.Items[i].Text;
					
					if(i == 0) {
						
					} else if (i !== 0 && i != (leg.Itinerary.Items.length - 1)) {
                        directions += " - " + "Go " + " " + leg.Itinerary.Items[i].Distance.toFixed(1) + " " + "miles";
                    } else if (i == (leg.Itinerary.Items.length - 1)) {
                    	directions += "at " + MapView._lastRoute.end;
                    }
                    directions += "</td></tr>\n";
                }
                directions += "<tr><td class='direction_listing_cell'>&nbsp;</td><td class='direction_listing_cell'>";
                directions += "Distance" + ": <b>" + route.Distance.toFixed(1) + " " + "miles" + "</b><br />";
                directions += "Time" + ": <b>" + (route.Time / 3600).toFixed(1) + " " + "hours" + "</b><br /><br />\n";
                if (MapView._lastRoute.reverse) {
                    directions += "<p><a href='javascript:MapView.reverseDirections(false);'>" + "Directions To Dealership" + "</a></p>";
                } else {
                    directions += "<p><a href='javascript:MapView.reverseDirections(true);'>" + "Reverse Directions" + "</a></p>";
                }
                directions += "</td></tr></table>";

                //var distance = "<p>" + route.Distance.toFixed(1) + " " + "miles" + " " + "away" + "</p>";
                $("dealer_map_turn_list").innerHTML = "<strong>Driving Directions:</strong><br />" + directions;

            }
        } else {
            $$(".directions_error").each(function(error) {
                //invalid address
                error.update("Address is invalid");
                error.show();
            });
        }
    },

    reverseDirections: function(isReverse) {
        if (MapView._lastRoute != null) {
            if (isReverse) {
                this.getDrivingDirections(MapView._lastRoute.start, MapView._lastRoute.end, MapView._lastRoute.dealerCode, true);
            } else {
                this.getDrivingDirections(MapView._lastRoute.start, MapView._lastRoute.end, MapView._lastRoute.dealerCode, false);
            }
        }

    },

    clearMap: function() {
        try {
            if (this._dealermap != null) {
                this._dealermap.Clear();
            }
        }
        catch(e) {}
    },

    buildDrivingDirectionsBlock: function(dealer) {
        var dealerAddress = "";
        if (dealer.address != null) {
            dealerAddress = dealer.address.addressLine1;
            if (dealer.address.addressLine2 != null && dealer.address.addressLine2 != "") {
                dealerAddress += " " + dealer.address.addressLine2;
            }
            dealerAddress += ", " + dealer.address.city + ", " + dealer.address.state + " " + dealer.address.zipCode;
        }

        var startAddressNode = Builder.node('input', {
            'id': 'startAddress',
            'name': 'startAddress',
            'type': 'text',
            'style': 'width: 150px;'
        });
        
        var endAddressNode = Builder.node('input', {
            'id': 'endAddress',
            'name': 'endAddress',
            'type': 'hidden',
            'value': dealerAddress
        });
        
        var submitNode = Builder.node('input', {
            'type': 'submit',
            'value': 'Go'
        });
        return [Builder.node('h3', 'Driving Directions:'),
        Builder.node('form', {
            'id': 'getDirectionsToDealerForm_' + dealer.dealerCode,
            'class': 'getDirectionsForm',
            'onsubmit': "MapView.getDrivingDirectionsFromForm(this, '" + dealer.dealerCode + "'); return false;"
        },
        [startAddressNode, endAddressNode, submitNode]
        )
        //,
        //Builder.node('div', {
        //    'id': 'dealer_map_turn_list_' + dealer.dealerCode
        //})

        ];

    },

    displayDealerMap: function displayDealerMap(dealerResults) {
        this._dealerPoints = new Array();
        if (dealerResults != null) {
            if (this._dealermap == null) {
                this._dealermap = new VEMap("dealer-map");
                this._dealermap.LoadMap();
            }

            this.clearMap();

            var layer = new VEShapeLayer();
            layer.SetTitle("DealerMapLayer");

            for (var i = 0; i < dealerResults.length; i++) {
                this._dealerPoints[this._dealerPoints.length] = new VELatLong(dealerResults[i].worldLatitude, dealerResults[i].worldLongitude);

                //add points
                var shape = new VEShape(VEShapeType.Pushpin, this._dealerPoints[i]);
                //shape = constructVEMapShape(shape, this._dealerPoints[i]);
                shape.SetCustomIcon("<div class='dealer-pin'>" + dealerResults[i].id + "</div>");
                shape.SetTitle("<div id='dealer-map-details-name'>" + dealerResults[i].dealerName + "</div>");

                var dealerAddress = "<div id='dealer-map-details-address'>";
                if (dealerResults[i].address != null) {
                    dealerAddress += dealerResults[i].address.addressLine1 + "<br />";
                    if (dealerResults[i].address.addressLine2 != null && dealerResults[i].address.addressLine2 != "") {
                        dealerAddress += dealerResults[i].address.addressLine2 + "<br />";
                    }
                    dealerAddress += dealerResults[i].address.city + ", " + dealerResults[i].address.state + " " + dealerResults[i].address.zipCode;
                }
				        dealerAddress += "</div>";
				
                var dealerPhoneNumber = "<div id='dealer-map-details-phone'>";
                if (dealerResults[i].phoneNumber != null) {
                    dealerPhoneNumber += dealerResults[i].phoneNumber;
                }
        				dealerPhoneNumber += "</div>";
        				
        				dealerDrivingDirections = "<div id='dealer-map-details-driving-directions-" + dealerResults[i].dealerCode + "'>";				
        				var buildingDrivingDirectionsBlock = Builder.node('p', this.buildDrivingDirectionsBlock(dealerResults[i]));
        				dealerDrivingDirections += buildingDrivingDirectionsBlock.innerHTML;
        				dealerDrivingDirections += "</div>";
                shape.SetDescription(dealerAddress + dealerPhoneNumber + dealerDrivingDirections);


                layer.AddShape(shape);
            }
            this._dealermap.AddShapeLayer(layer);

            //center map view
            this._dealermap.SetMapView(this._dealerPoints);
        }
    },

    constructVEMapShape: function(shape, dealer) {
        shape.SetCustomIcon("<div class='dealer-pin'>" + dealer.id + "</div>");


        shape.SetTitle(dealer.dealerName);

        var dealerAddress = "";
        if (dealer.address != null) {
            dealerAddress = dealer.address.addressLine1 + "<br />";
            if (dealer.address.addressLine2 != null && dealer.address.addressLine2 != "") {
                dealerAddress += dealer.address.addressLine2 + "<br />";
            }
            dealerAddress += dealer.address.city + ", " + dealer.address.state + " " + dealer.address.zipCode + "<br />";
        }

        var dealerPhoneNumber = "";
        if (dealer.phoneNumber != null) {
            dealerPhoneNumber = dealer.phoneNumber;
        }

        shape.SetDescription(dealerAddress + dealerPhoneNumber);

        return shape;
    }
}


var DealerDetailView = {

    renderSideBar: function(id) {
        $('dealer-details-content').update('');

        var dealer = allDealers.find(function(d) {
            return d.id == id;
        });

        var address = dealer.address.addressLine1;
        var city = dealer.address.city;
        var state = dealer.address.state;
        var zip = dealer.address.zipCode;
        var phone = dealer.phoneNumber

        var details = [
        Builder.node('strong', dealer.dealerName),
        Builder.node('br'),
        address,
        Builder.node('br'),
        city, ', ', state, ' ', zip,
        Builder.node('br'),
        phone,
        Builder.node('br'),
        Builder.node('a', {
            'href': dealer.uri,
            'target':'_blank',
            'class':'button'
        },
        Builder.node('span', 'Dealer Website'))
        ];



        var contact = [
        Builder.node('strong', 'Sales/Main:'),
        Builder.node('br'),
        'Tel: ' + dealer.phoneNumber,
        Builder.node('br'),
        'Fax: ' + dealer.faxNumber
        ]

        var hours = [];
        var hoursArray = this.buildHoursOfOperations(dealer);
        
        if(this.hasHoursOfOperations(hoursArray)) { 
        	hours = [Builder.node('br'), hoursArray];
        }


        var services = $A();
        dealer.dealerAttributes.each(function(a) {
            this.push(Builder.node('br'));
            var url = dealerAttributeUrlMap.get(a.dealerAttributeId) || '#';
            this.push(Builder.node('a', {
                'href': url,
                'target':'_blank'
            },
            a.dealerAttributeName));
        },
        services);

		var dealerCoupons = DealerDetailView.buildDealerCoupons(dealer);        

        var quickLinks = [
        Builder.node('br'),
        Builder.node('a', {
            'href': 'http://www.buyatoyota.com/deeplinks/specials.aspx?zip_code=' + zip,
            'target':'_blank'
        },
        'Local Specials'),
        Builder.node('br'),
        Builder.node('a', {
            'href': 'http://www.toyota.com/tcuv/results.html?language=E&SearchDealerCode=' + dealer.dealerCode,
            'target':'_blank'
        },
        'Search Used Inventory'),
        dealerCoupons
        ]


        var drivingDirections = MapView.buildDrivingDirectionsBlock(dealer);

        $('dealer-details-content').insert({
            'bottom': Builder.node('p', details)
        });
        $('dealer-details-content').insert({
            'bottom': Builder.node('p', contact)
        });
        $('dealer-details-content').insert({
            'bottom': Builder.node('p', [Builder.node('strong', 'HOURS OF OPERATION'), hours])
        });
        $('dealer-details-content').insert({
            'bottom': Builder.node('p', drivingDirections)
        });
        $('dealer-details-content').insert({
            'bottom': Builder.node('p', [Builder.node('strong', 'SERVICES & DISTINCTIONS'), services])
        });
        $('dealer-details-content').insert({
            'bottom': Builder.node('p', [Builder.node('strong', 'QUICK LINKS'), quickLinks])
        });

        ViewHandler.showDealerDetailView();
        var dealerDetailArray = new Array();
        dealerDetailArray[dealerDetailArray.length] = dealer;
        MapView.displayDealerMap(dealerDetailArray);
    },
    
    buildDealerCoupons: function(dealer) {
    	var dealerCoupons = Builder.node('div', { id: 'dealerCoupons'});
    	var couponLinkText = "View Service Offers";
    	var couponMoreLinkText = "View More Service Offers";
    	
		if(dealer.coupons != null && dealer.coupons.length > 0) {
			var couponLink = null;
			var couponCount = 0;
	       	for (var i=0;i<dealer.coupons.length;i++) {
	       		var tmpCoupon = dealer.coupons[i];
	       		if(tmpCoupon != null) {
	       			if(tmpCoupon.couponType == "COUPON_PDF") {	
	       				couponCount = couponCount + 1;       			
		       			couponLink = "/pub/coupons/" + tmpCoupon.couponPdf;
		       			if(couponCount > 1) {
		       				couponLinkText = couponMoreLinkText;
		       			}
		       			var coupon = Builder.node('a', {
				            'href': couponLink,
				            'target':'_blank'
					        }, [couponLinkText, Builder.node('br')]);
					    dealerCoupons.appendChild(coupon);
					    
		       			
	       			} else if (tmpCoupon.couponType == "COUPON_URL") {
	       				couponCount = couponCount + 1;
	       				couponLink = tmpCoupon.couponUrl;
	       				if(couponCount > 1) {
		       				couponLinkText = couponMoreLinkText;
		       			}
	       				var coupon = Builder.node('a', {
				            'href': couponLink,
				            'target':'_blank'
					        }, [couponLinkText, Builder.node('br')]);
					    dealerCoupons.appendChild(coupon);
	       			}
				}
			}	       	
		}
    	return dealerCoupons;
    },
    
	buildHoursOfOperations: function(dealer) {
    	
    	var hours = [];
    	var hoursGeneral = [];
    	var hoursParts = []
    	var hoursService = [];
    	var hoursFinance = [];
    	
    	if (dealer.hours != null && dealer.hours != "") {
            hoursGeneral = [   
            Builder.node('strong', 'General Hours'),         
            Builder.node('br'),
            "Monday: " + dealer.hours.Monday,
            Builder.node('br'),
            "Tuesday: " + dealer.hours.Tuesday,
            Builder.node('br'),
            "Wednesday: " + dealer.hours.Wednesday,
            Builder.node('br'),
            "Thursday: " + dealer.hours.Thursday,
            Builder.node('br'),
            "Friday: " + dealer.hours.Friday,
            Builder.node('br'),
            "Saturday: " + dealer.hours.Saturday,
            Builder.node('br'),
            "Sunday: " + dealer.hours.Sunday,
            Builder.node('br'),
            Builder.node('br')
            ];
        }
        
        if (dealer.hoursParts != null && dealer.hoursParts != "") {
            hoursParts = [
            Builder.node('strong', 'Parts Hours'),
            Builder.node('br'), 
            "Monday: " + dealer.hoursParts.Monday,
            Builder.node('br'),
            "Tuesday: " + dealer.hoursParts.Tuesday,
            Builder.node('br'),
            "Wednesday: " + dealer.hoursParts.Wednesday,
            Builder.node('br'),
            "Thursday: " + dealer.hoursParts.Thursday,
            Builder.node('br'),
            "Friday: " + dealer.hoursParts.Friday,
            Builder.node('br'),
            "Saturday: " + dealer.hoursParts.Saturday,
            Builder.node('br'),
            "Sunday: " + dealer.hoursParts.Sunday,
            Builder.node('br'),
            Builder.node('br')
            ];
        }
        
        if (dealer.hoursService != null && dealer.hoursService != "") {
            hoursService = [
            Builder.node('strong', 'Service Hours'),
            Builder.node('br'), 
            "Monday: " + dealer.hoursService.Monday,
            Builder.node('br'),
            "Tuesday: " + dealer.hoursService.Tuesday,
            Builder.node('br'),
            "Wednesday: " + dealer.hoursService.Wednesday,
            Builder.node('br'),
            "Thursday: " + dealer.hoursService.Thursday,
            Builder.node('br'),
            "Friday: " + dealer.hoursService.Friday,
            Builder.node('br'),
            "Saturday: " + dealer.hoursService.Saturday,
            Builder.node('br'),
            "Sunday: " + dealer.hoursService.Sunday,
            Builder.node('br'),
            Builder.node('br')
            ];
        }
        
        if (dealer.hoursFinance != null && dealer.hoursFinance != "") {
            hoursFinance = [
            Builder.node('strong', 'Finance Hours'),
            Builder.node('br'), 
            "Monday: " + dealer.hoursFinance.Monday,
            Builder.node('br'),
            "Tuesday: " + dealer.hoursFinance.Tuesday,
            Builder.node('br'),
            "Wednesday: " + dealer.hoursFinance.Wednesday,
            Builder.node('br'),
            "Thursday: " + dealer.hoursFinance.Thursday,
            Builder.node('br'),
            "Friday: " + dealer.hoursFinance.Friday,
            Builder.node('br'),
            "Saturday: " + dealer.hoursFinance.Saturday,
            Builder.node('br'),
            "Sunday: " + dealer.hoursFinance.Sunday,
            Builder.node('br'),
            Builder.node('br')
            ];
        }
        
        hours = [hoursGeneral, hoursParts, hoursService, hoursFinance];
        
        return hours;
    }, 
    
   	hasHoursOfOperations: function(hours) {
   		if (hours != null && hours.length == 4) {
   			if(hours[0].length > 0 || hours[1].length > 0 || hours[2].length > 0 || hours[3].length > 0) {
   				return true;
   			}
   		}
   		return false;
   	}  
}


var ViewHandler = {
    toggleTabs: function(tabs) {
        tabs = $H(tabs);

        tabs.get('show').each(function(s) {
            $(s).show();
        });

        tabs.get('hide').each(function(s) {
            $(s).hide();
        });

        $(tabs.get('show_btn')).addClassName('selected');
        $(tabs.get('hide_btn')).removeClassName('selected');
    },

    showDealerDetailView: function() {
        $('tabs').hide();
        $('dealer_view').hide();
        $('dealer_map_listings').hide();

        $('dealer_map_turn_list').update('');
        $('map-and-dealer-detail-view-container').show();
        $('dealer-detail-header').show();
        $('dealer-details-container').show();
        $('map-container').show();
    },

    hideDealerDetailView: function() {
        $('tabs').show();
        $('dealer_view').show();

        $('dealer-detail-header').hide();
        $('dealer-details-container').hide();
        $('map-and-dealer-detail-view-container').hide();
        $('map-container').hide();
    },

    clearErrors: function() {
        $$('div.errors').each(function(d) {
            d.update('');
        });
    },

    newSearch: function() {
        window.location = '/Owners/dealer/locator.do';
    },
    
    backToSearchResults: function() {
        ViewHandler.toggleTabs({'show': ['dealer_view'],
                                'hide': ['map-and-dealer-detail-view-container', 'dealer_map_listings'],
                                'show_btn':'list_button',
                                'hide_btn':'map_button'
        });    
    }
}

var PreferredDealer = {

  formBlock: function(dealerCode) {
  
    var li_applyAll = Builder.node('li', [
      Builder.node('input', {
        'type':'checkbox',
        'onclick':'PreferredDealer.handleCheckBox(\'' + dealerCode +'\', this);'
      }), 'Apply to all vehicles'
    ]);

    var li_confirm = Builder.node('li', [
      Builder.node('input', {
        'type':'checkbox',
        'id':'confirmPreferred' + dealerCode
      }),
      Builder.node('span', {'id':'preferredCheckbox' + dealerCode}, 'Confirm your selected changes')
  	]);
  	
  	var li_vehiclesList = Builder.node('li', PreferredDealer.vehicleDropDown(dealerCode)); 	
  	
  	var li_currentPreferredDealer = null;
  	
  	var li_errors = Builder.node('li', Builder.node('div', {
  		'id':'preferredFormErrors' + dealerCode,
  		'style':'color: red'
    }));
  	
  	
  	
  	var li_submit = Builder.node('input', {'type':'submit', 'value':'Submit'});
  	
  	var ul_fields = Builder.node('ul', [
  		li_vehiclesList,  	
  		li_applyAll,
  		li_confirm,
  		li_errors,
  		li_submit
  	]);
    
    var dealerCodeField = Builder.node('input', {
      'type':'hidden',
      'name':'dealerCode',
      'value':dealerCode
    });
    
    var submitAction = Builder.node('input', {
      'type':'hidden',
      'name':'submitAction',
      'value':'changeDealer'
    });
    
    var vehicleId = Builder.node('input', {
      'type':'hidden',
      'name':'vehicleId',
      'id':'preferredVehicleId' + dealerCode,
      'value':'0'
    });
    
    var form = Builder.node('form', {
      'action':'/',
      'id':'preferredForm' + dealerCode,
      'class':'preferredDealerForm',
      'onsubmit':'return DealerLocator.changePreferredDealer(\'' + dealerCode + '\');'
    }, [dealerCodeField, submitAction, vehicleId, ul_fields]);
    
    return form;
  },
  
  loggedIn: function(dealerCode, closeLink) {
	var preferredContainer = Builder.node('div', {
      'style':'display: none;',
      'class':'preferredDealerContainer',
      'id':'preferredContainer_' + dealerCode
    }, [
      Builder.node('div', {
        'id':'preferredDealerInfo' + dealerCode,
        'class':'dealerInfo'
      }),
      Builder.node('div', {'class':'preferredDealerFormContainer'}, [closeLink, PreferredDealer.formBlock(dealerCode)])
    ]);    
  
	return preferredContainer;    
  },
  
  notLoggedIn: function(dealerCode, closeLink) {
  	var loginLink = Builder.node('a', {'href':'/Owners/mytoyota/auth/ssl/OwnersLogin'}, 'log in'); 	
  	var registerLink = Builder.node('a', {'href':'/Owners/ssl/nonauth/registration/registration.do'}, 'here');
  	
  	var msg = new Array();
  	msg[0] = 'To set your preferred dealer please ';	
  	msg[1] = '. If you do not have an account, please register ';
  	msg[2] = '.';
  
	var msg = Builder.node('div', {'style':'margin-top: 20px'}, [
		msg[0], loginLink, msg[1], registerLink, msg[2]
	]);	
	
	var preferredContainer = Builder.node('div', {
      'style':'display: none;',
      'class':'preferredDealerContainer',
      'id':'preferredContainer_' + dealerCode
    }, 
      Builder.node('div', {'class':'preferredDealerFormContainer'}, [closeLink, msg])
  	);    
  
  	return preferredContainer;
  },
  
  preferredContainer: function(dealerCode, customerVehiclesSize) {
	var closeLink = Builder.node('a', {
      'href':'#',
      'class':'preferredCloseLink',
      'onclick':'PreferredDealer.closeForm(\'' + dealerCode + '\'); return false'
    }, '[x] Close');
    
	var preferredLink = Builder.node('a', {
      'href':'#',
      'class':'button',
      'onclick':'PreferredDealer.showForm(\'' + dealerCode + '\'); return false'
    }, Builder.node('span', 'Select'));      

	var preferredContent = "";
	
	  	if (this.isUserLoggedIn() && customerVehiclesSize > 0) {
	  	  preferredContent = PreferredDealer.loggedIn(dealerCode, closeLink);
	  	  return [preferredLink, preferredContent]; 
	  	} else if (!this.isUserLoggedIn()){
	  	  preferredContent = PreferredDealer.notLoggedIn(dealerCode, closeLink);
	  	  return [preferredLink, preferredContent]; 
	  	}
		
	return preferredContent;
  	   
  },

  handleCheckBox: function(dealerCode, field) {
    if (field.checked) {
      PreferredDealer.setPreferredVehicleId(dealerCode, 0);
      $('selectVehicleId' + dealerCode).disable();
    } else {
      $('selectVehicleId' + dealerCode).enable();
    }
  },
  
  vehicleDropDown: function(dealerCode) {
  	var options = $A();
  	options.push(Builder.node('option', {'value':''}, 'Select a vehicle'));
  	
  	customerVehicles.each(function(v) {
  		options.push(Builder.node('option', {
  			'value':v.vehicleId
  		}, v.year + ' ' + v.make + ' ' + v.model));
  	});
  	
  	return Builder.node('select', {
  	   'id':'selectVehicleId' + dealerCode,
  	   'class':'vehiclesList',
       'onchange':'PreferredDealer.setPreferredVehicleId(\'' + dealerCode + '\', this.value); PreferredDealer.displayDealerInfo(\'' + dealerCode + '\', this.value)' 
    }, options);	
  },
  
  displayDealerInfo: function(dealerCode, vehicleId) {
    var v = customerVehicles.find(function(i) {
      return i.vehicleId == vehicleId;
    });
    
    var info = $('preferredDealerInfo' + dealerCode);
    
    if (v != null && v.preferredDealer.dealerCode != '') {
      
      info.update('');
      info.insert({'bottom':Builder.node('p', Builder.node('strong', 'Preferred Dealer'))});
      info.insert({'bottom':Builder.node('p', [
        v.preferredDealer.name,
        Builder.node('br'),
        v.preferredDealer.address.addressLine1,
        Builder.node('br'),
        v.preferredDealer.address.city + ', ',
        v.preferredDealer.address.state + ' ',
        v.preferredDealer.address.zipCode
      ])});      
    } else {
      info.update('');
      info.insert({'bottom':Builder.node('p', Builder.node('strong', 'Preferred Dealer'))});
      info.insert({'bottom':Builder.node('p', '(None Selected)' )});    
    }
  },
  
  setPreferredVehicleId: function(dealerCode, val) {
    $('preferredVehicleId' + dealerCode).value = val;
  },
  
  showForm: function(dealerCode) {
    $('preferredContainer_' + dealerCode).appear({duration: 0.5});  
  },
  
  closeForm: function(dealerCode) {
    $('preferredContainer_' + dealerCode).fade({duration: 0.5});     
  }, 
  
  isUserLoggedIn: function () {
  	if ($('homeLink') != null) {
  		var homeLink = $('homeLink').href;
  		if(homeLink.indexOf('/Owners/account-overview.do') != -1) {
  			return true;
  		}
  	}
  	return false;
  }
}

var UrlUtil = {
	/**
	 * Returns the value of the url parameter specified in the argument
	 */
	 getUrlParam: function(name) {
		name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
		var regexS = "[\\?&]"+name+"=([^&#]*)";
		var regex = new RegExp( regexS );
		var results = regex.exec( window.location.href );
		
		if (results == null) {
			return "";
		} else {
			return results[1];
		}
	}
}
