﻿/// <reference path="mootools-core.js" />

// #region Global Variables

// Carousels
var pg = pg || [];
var pb = pb || [];

// Utility Panel
var utilityPanelControlPrefix = "jscUtilityPanel_";
var promptForDefaultLocationTextBox = "enter place or postcode";
var promptForLocationTextBoxWithPolygon = "using your drawn area";
var drawASearchIndicatorShown = false;
var geocoder;

// Google Map
var polygonMap; // The map
var polygonMarkers = []; // Markers for the main polygon points
var polygonMidMarkers = []; // Markers for the polygon line mid points
var polyShape; // The polyline or polygon dependent on the mode
var polylineGhost; // The polyline ghost for dragging / dropping

var polygonEditMode = 0; // 0 = polyline, 1 = polygon

var polygonBorderColour = "#FF0000";
var polygonFillColour = "#0000FF";
var polylineColour = "#FF0000";
var polylineGhostColour = "#00FF00";

var utiliyPanelPreLoadImages = [
	"/images/jsPSTitle.png",
	"/images/multiSelectMonitorCentre.png",
	"/images/multiSelectMonitorLeft.png",
	"/images/multiSelectMonitorRight.png",
	"/images/multiSelectMonitorRightRO.png",
	"/images/newsClose.png",
	"/images/newsCloseRO.png",
	"/images/registerClose.png",
	"/images/registerCloseRO.png",
	"/images/searchBack.png",
	"/images/searchBackRO.png",
	"/images/searchClose.png",
	"/images/searchCloseRO.png",
	"/images/searchFind.png",
	"/images/searchFindRO.png",
	"/images/searchReset.png",
	"/images/searchResetRO.png",
	"/images/searchPolygonButton.png",
	"/images/searchPolygonButtonRO.png",
	"/images/submitRegistration.png",
	"/images/submitRegistrationRO.png"
];
// #endregion


// #region General Routines

var setupDrawASearchIndicator = function () {
    $('DrawASearchIndicator').setStyle('visibility', 'hidden');
    $('DrawASearchIndicator').setStyle('opacity', 0);

    $(utilityPanelControlPrefix + 'txtSearchLocation').addEvent('focus', function () {
        showDrawASearchIndicator();
    });

    $('jsPSDefinePolygon').addEvent('mouseover', function () {
        showDrawASearchIndicator();
    });
};
var showDrawASearchIndicator = function () {
    if (!drawASearchIndicatorShown) {
        drawASearchIndicatorShown = true;
        var fx = new Fx.Morph('DrawASearchIndicator', {
            duration: 1000,
            transition: Fx.Transitions.Quart.easeOut
        });

        $('DrawASearchIndicator').setStyle('opacity', 0);
        $('DrawASearchIndicator').setStyle('visibility', 'visible');
        fx.start({
            'opacity': 1
        }).chain(function () {
            this.start.delay(10000, this, {
                'opacity': 0
            });
        }).chain(function () {
            $('DrawASearchIndicator').setStyle('visibility', 'hidden');
        });
    }
};

var bindLightbox = function () {
    $$('a > img').each(function (item, index) {
        var a = item.getParent('a');
        if (a != null) {
            var href = item.getParent('a').getProperty('href');
            img = a.getChildren('img');
            if (img != null) {
                if (img.getProperty('alt') != null) {
                    a.setProperty('title', img.getProperty('alt'));
                }
            }
            if (href.substr(href.length - 4) == '.jpg') {
                a.slimbox();
            }
        }
    });
}

var applyTextBoxPrompts = function () {
    $$('input[rel]').each(function (el) {
        var isErr = false;
        var pass = el.get('type') == 'password';
        el.addEvents({
            focus: function () {
                if (el.get('value') == el.get('rel')) {
                    el.set('value', '');
                    el.removeClass('promptText');
                    if (el.hasClass('err')) {
                        isErr = true;
                        el.removeClass('err');
                    }
                    if (pass) el.set('type', 'password');
                }
            },
            blur: function () {
                var val = el.get('value');
                if (!val || val == el.get('rel')) {
                    el.set('value', el.get('rel'));
                    el.addClass('promptText');
                    if (pass) el.set('type', 'text');
                    if (isErr) el.addClass('err');
                }
                isErr = false;
            }
        }).fireEvent('blur');
    });

    $$('textarea[rel]').each(function (el) {
        var isErr = false;
        el.addEvents({
            focus: function () {
                if (el.get('value') == el.get('rel')) {
                    el.set('value', '');
                    el.removeClass('promptText');
                    if (el.hasClass('err')) {
                        isErr = true;
                        el.removeClass('err');
                    }
                }
            },
            blur: function () {
                var val = el.get('value');
                if (!val || val == el.get('rel')) {
                    el.set('value', el.get('rel'));
                    el.addClass('promptText');
                    if (isErr) el.addClass('err');
                }
                isErr = false;
            }
        }).fireEvent('blur');
    });
};
var validateEmail = function (email) {
    var atpos = email.indexOf("@");
    var dotpos = email.lastIndexOf(".");
    if (atpos < 1 || dotpos < atpos + 2 || dotpos + 2 >= email.length) {
        return false;
    } else {
        return true;
    }
};
// #endregion

// #region Utility Panel

// #region Panel Control

/// <summary>Sets the visbility of panels</summary>
/// <param name="visiblePanel" type="String">ID of the panel to show, if blank then last panel stored in cookie shown or if not recognised all panels hidden. </param>
var jsUPSetVisibility = function (visiblePanel) {
    $("jsPanelSearch").addClass("MakeInvisible");
    $("jsPanelNews").addClass("MakeInvisible");
    $("jsPanelRegister").addClass("MakeInvisible");

    if (visiblePanel == "") {
        visiblePanel = Cookie.read("visibleUPPanel");
    }
    else {
        var myCookie = Cookie.write("visibleUPPanel", visiblePanel);
    }

    // visblePanel = "register"; - used for debug
    switch (visiblePanel) {
        case "search":
            $("jsPanelSearch").removeClass("MakeInvisible");
            break;
        case "news":
            $("jsPanelNews").removeClass("MakeInvisible");
            break;
        case "register":
            $("jsPanelRegister").removeClass("MakeInvisible");
            break;
        default:
    }
};
// #endregion Panel Control

// #region Search Panel

/// <summary>Stores the current search data</summary>
var jsUPStoreSearch = function () {
    var oldCookie = Cookie.dispose("UPSearchJSON");

    var JSON = '';
    $$('#jsPanelSearch INPUT').each(function (item) {
        JSON += '{';
        JSON += '"controlID":"' + item.getProperty('id') + '", ';
        JSON += '"controlType":"input", ';
        switch (item.getProperty('type').toUpperCase()) {
            case "CHECKBOX":
                JSON += '"controlValue":"' + item.checked + '"}, ';
                break;
            default:
                JSON += '"controlValue":"' + item.value + '"}, ';
        }
    });

    $$('#jsPanelSearch SELECT').each(function (item) {
        JSON += '{';
        JSON += '"controlID":"' + item.getProperty('id') + '", ';
        JSON += '"controlType":"select", ';
        JSON += '"controlValue":"' + item.selectedIndex + '"}, ';
    });

    JSON = '[ ' + JSON.substr(0, JSON.length - 1) + ' ]';

    var myCookie = Cookie.write("UPSearchJSON", JSON);
};
/// <summary>Restores current search data</summary>
var jsUPRestoreSearch = function () {
    var storedSearchJSON = Cookie.read("UPSearchJSON");
    if (storedSearchJSON) {
        var searchSettings = JSON.decode(storedSearchJSON);

        for (var i = 0; i < searchSettings.length; i++) {
            try {
                //document.write("controlID : " + item.controlID + ", controlType : " + item.controlType + ", controlValue : " + item.controlValue + "<br />");
                //if (document.getElementById(item.id)) {
                if ($(searchSettings[i].controlID)) {
                    switch (searchSettings[i].controlType.toUpperCase()) {
                        case "INPUT":
                            switch ($(searchSettings[i].controlID).type.toUpperCase()) {
                                case "CHECKBOX":
                                    if (searchSettings[i].controlValue.toUpperCase() == "TRUE") {
                                        $(searchSettings[i].controlID).checked = true;
                                    } else {
                                        $(searchSettings[i].controlID).checked = false;
                                    }
                                    break;
                                default:
                                    $(searchSettings[i].controlID).value = searchSettings[i].controlValue;
                            }

                            //document.getElementById(item.id).value = item.controlValue;
                            break;
                        case "SELECT":
                            $(searchSettings[i].controlID).selectedIndex = searchSettings[i].controlValue;
                            //document.getElementById(item.id).selectedIndex = item.controlValue;
                            break;
                    }
                }
                //}
            }
            catch (err) {
            }
        }

        if ($(utilityPanelControlPrefix + 'txtSearchLocation').value == promptForDefaultLocationTextBox ||
			$(utilityPanelControlPrefix + 'txtSearchLocation').value == promptForLocationTextBoxWithPolygon)
            $(utilityPanelControlPrefix + 'txtSearchLocation').set('rel', $(utilityPanelControlPrefix + 'txtSearchLocation').value);
    }
};
var ResetSearch = function () {
    $(utilityPanelControlPrefix + 'txtSearchLocation').value = "";
    $(utilityPanelControlPrefix + 'txtSearchLocation').fireEvent("blur");
    $(utilityPanelControlPrefix + 'cboRadius').value = 0;
    $(utilityPanelControlPrefix + 'cboDateAdded').value = 2000;
    $(utilityPanelControlPrefix + 'cboFromValue').value = 0;
    $(utilityPanelControlPrefix + 'cboToValue').value = 999999999;
    $(utilityPanelControlPrefix + 'cboBedroomsFrom').value = 0;
    $(utilityPanelControlPrefix + 'cboBedroomsTo').value = 99;
    //$(utilityPanelControlPrefix + 'chkIncludeUnderOffer').checked = false;

    $$('#jsPanelSearch input[type=checkbox]').each(function (item) {
        if (item.checked = true) {
            item.checked = false;
        }
    });

    var myMultiSelect = new MultiSelect('.MultiSelectOutlook', { zeroSelectedText: 'show all characteristics' });
    var myMultiSelect2 = new MultiSelect('.MultiSelectPropertyType', { zeroSelectedText: 'show all types' });

    return false;
};
// #endregion Search Panel

// #region Register Panel

/// <summary>Used to save registration (not implemented)</summary>
var jsUPStoreRegister = function () {
};
/// <summary>Used to restore registration (not implemented)</summary>
var jsUPRestoreRegister = function () {
};
/// <summary>Checks whether the registration is valid, highlights errors and returns whether valid or not</summary>
/// <returns type="boolean">Whether the registration details are valid</returns>
var checkRegistrationValid = function () {
    var everythingOK = true;

    $$('#jsPanelRegister input[type=text]').each(function (item) {
        item.removeClass('err');
        if (item.get("required")) {
            if (!checkValidInputText(item.id)) {
                item.addClass('err');
                everythingOK = false;
            }
        }
    });

    $$('#jsPanelRegister textarea').each(function (item) {
        item.removeClass('err');
    });

    $$('#jsPanelRegister input[type=checkbox]').each(function (item) {
        item.removeClass('err');
    });

    if (!validateEmail($(utilityPanelControlPrefix + 'txtRegisterEmail').value)) {
        $(utilityPanelControlPrefix + 'txtRegisterEmail').addClass('err');
        everythingOK = false;
    }

    return everythingOK;
};
var checkValidInputText = function (controlID) {
    try {
        var relText = $(controlID).get('rel');
        if ($(controlID).value != relText && $(controlID).value) {
            return true;
        } else {
            var reqText = $(controlID).get('required');
            if (reqText == 'true') {
                return false;
            } else {
                return true;
            }
        }
    } catch (e) {
        return false;
    }
};
// #endregion Register Panel

// #region Polygon Plotter Control

/// <summary>Shows the Polygon Plotter</summary>
var showPolygonPlotter = function () {
    // Don't do anything if modal showing - this should never happen
    if ($('polygonmodal')) {
        hidePolygonPlotter(false);
        return false;
    }

    // Stop any carousels
    if (pg.tmp) {
        window.clearInterval(pg.tmp);
    }

    // Create modal surround and get it to adopt the map
    var modalDIV = new Element('div', {
        id: 'polygonmodal',
        'class': 'modalbackground',
        styles: {
            position: 'absolute',
            top: 0,
            left: 0,
            width: window.getScrollWidth(),
            height: window.getScrollHeight(),
            'z-index': 10000
        }
    }).adopt($('PolygonWrapper'));

    // Inject the modal surround into the document
    modalDIV.inject(document.body);

    // Initialise the map
    $('PolygonWrapper').removeClass('MakeInvisible');
    initializePolygonMap('polygon_map_canvas');
    loadPolygonMapPolygon(utilityPanelControlPrefix + 'hdnPolygonVertices');
    plotPropertiesOnPolygonMap();
};
/// <summary>Hides the Polygon Plotter</summary>
/// <param name="savePolygon" type="boolean">Whether to save the polygon drawn</param>
var hidePolygonPlotter = function (savePolygon) {
    // Save Polygon?
    if (savePolygon) {
        savePolygonMapPolygon(utilityPanelControlPrefix + 'hdnPolygonVertices');
        $(utilityPanelControlPrefix + 'txtSearchLocation').set('rel', promptForLocationTextBoxWithPolygon);
        $(utilityPanelControlPrefix + 'txtSearchLocation').set('value', promptForLocationTextBoxWithPolygon);
        jsUPStoreSearch();
    }

    // Clear map
    clearPolygonMap();

    // Get the map DIV otherwise it will be destroyed!
    $('polygonmodal').fade(0);
    $('PolygonWrapper').addClass('MakeInvisible');
    $(document.body).grab($('PolygonWrapper'));
    $('polygonmodal').dispose();

    // Start the carousels again
    try {
        ld();
    } catch (e) {
    }
};
/// <summary>Handles clearing of the polygon map</summary>
var handlePolygonPlotterClear = function () {
    $(utilityPanelControlPrefix + 'txtSearchLocation').set('rel', promptForDefaultLocationTextBox);
    $(utilityPanelControlPrefix + 'txtSearchLocation').set('value', promptForDefaultLocationTextBox);
    $(utilityPanelControlPrefix + 'hdnPolygonVertices').set('value', '');

    // Clear map
    clearPolygonMap();
};
// #endregion

// #region Location Geocoding

var CheckSubmit = function (e) {
    var e = (e) ? e : event;
    var charCode = (e.which) ? e.which : e.keyCode;
    if (charCode == 13) {
        if (LookupAddress()) {
            __doPostBack('jscUtilityPanel$btnPrimarySearch', '');
        }
    }
};
/// <summary>Call for lookup of address to geocode if not using a polygon search</summary>
var LookupAddress = function () {
    if ($(utilityPanelControlPrefix + 'txtSearchLocation').get('rel') != $(utilityPanelControlPrefix + 'txtSearchLocation').get('value')) {
        var address = $(utilityPanelControlPrefix + 'txtSearchLocation').get('value');

        //request.address = address;
        //request.region = "uk";
        var swlatlng = new google.maps.LatLng(49, -7);
        var nelatlng = new google.maps.LatLng(51.5, -2);
        var latlngbounds = new google.maps.LatLngBounds(swlatlng, nelatlng);
        //request.bounds = latlngbounds;
        //geocoder.geocode(request, handleGeocodeResult);
        geocoder.geocode({ 'address': address, 'bounds': latlngbounds, 'region': 'uk' }, handleGeocodeResultBoundary);

        return false;
    } else {
        if ($(utilityPanelControlPrefix + 'hdnPolygonVertices').get('value')) {
            return true;
        } else {
            //location.replace("http://www.jackie-stanley.co.uk/search/all/");
            $(utilityPanelControlPrefix + 'txtSearchLocation').set('value', '');
            return true;
        }
    }
};
/// <summary>Handler for geocoding results</summary>
/// <param name="results" type="google.maps.GeocoderResult">Results from the geocoder request</param>
/// <param name="status" type="google.maps.GeocoderStatus">Status from the geocoder request</param>
var handleGeocodeResult = function (results, status) {
    //alert("Hello!" + status);
    if (status == google.maps.GeocoderStatus.OK) {
        var latLngAsString = results[0].geometry.location.toString().replace('(', '').replace(')', ''); //+ ',' + results[0].geometry.location.LatLng.lng().toString;
        $(utilityPanelControlPrefix + 'hdnPolygonVertices').set('value', latLngAsString);
        //$(utilityPanelControlPrefix + 'txtSearchLocation').set('value', latLngAsString);
        __doPostBack('jscUtilityPanel$btnPrimarySearch', '');
        //form1.submit();
    } else {
        $(utilityPanelControlPrefix + 'hdnPolygonVertices').set('value', '');
        __doPostBack('jscUtilityPanel$btnPrimarySearch', '');
        //alert("Location search was not successful for the following reason: " + status);
    }
};
/// <summary>Handler for geocoding results using the boundary</summary>
/// <param name="results" type="google.maps.GeocoderResult">Results from the geocoder request</param>
/// <param name="status" type="google.maps.GeocoderStatus">Status from the geocoder request</param>
var handleGeocodeResultBoundary = function (results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
        // First try to defined latlng bounds
        var resultBounds = results[0].geometry.bounds;
        if (!resultBounds) {
            // work on point if no latlng bounds
            var latLngAsString = results[0].geometry.location.toString().replace('(', '').replace(')', ''); //+ ',' + results[0].geometry.location.LatLng.lng().toString;
            $(utilityPanelControlPrefix + 'hdnPolygonVertices').set('value', latLngAsString);
            __doPostBack('jscUtilityPanel$btnPrimarySearch', '');
        } else {
            // Lat more north = +
            // Lng more east = +
            var neLatLng = results[0].geometry.bounds.getNorthEast();
            var swLatLng = results[0].geometry.bounds.getSouthWest();
            var north = ApplyRadiusToDimension(neLatLng.lat(), true);
            var east = ApplyRadiusToDimension(neLatLng.lng(), true);
            var south = ApplyRadiusToDimension(swLatLng.lat(), false);
            var west = ApplyRadiusToDimension(swLatLng.lng(), false);
            var boxString = north.toString() + ',' + west.toString() + ',' + north.toString() + ',' + east.toString() + ','
				+ south.toString() + ',' + east.toString() + ',' + south.toString() + ',' + west.toString();
            $(utilityPanelControlPrefix + 'hdnPolygonVertices').set('value', boxString);
            __doPostBack('jscUtilityPanel$btnPrimarySearch', '');
        }
    } else {
        $(utilityPanelControlPrefix + 'hdnPolygonVertices').set('value', '');
        __doPostBack('jscUtilityPanel$btnPrimarySearch', '');
    }
};
var ApplyRadiusToDimension = function (dimension, addRadius) {
    var radius = $(utilityPanelControlPrefix + 'cboRadius').value;
    if (radius) {
        if (addRadius) {
            return dimension + (radius / 69);
        } else {
            return dimension - (radius / 69);
        }
    } else {
        return dimension;
    }
};
// #endregion

// #endregion

// #region PolyMap

/// <summary>Initialise the polygon map</summary>
/// <param name="mapContainerID" type="String">The ID of the div to display the map into.</param>
var initializePolygonMap = function (mapContainerID) {
    if (!polygonMap) {
        var latlng = new google.maps.LatLng(50.538692, -4.941180000000031); // Padstow!

        // Define the Map Options according to http://code.google.com/apis/maps/documentation/javascript/reference.html#MapOptions
        var myOptions = {
            zoom: 13,
            center: latlng,
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            mapTypeControlOptions: {
                mapTypeIds: [google.maps.MapTypeId.ROADMAP, google.maps.MapTypeId.TERRAIN],
                style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
            },
            draggableCursor: 'auto',
            draggingCursor: 'move',
            disableDoubleClickZoom: false
        };

        // Specify the map according to http://code.google.com/apis/maps/documentation/javascript/reference.html#Map

        polygonMap = new google.maps.Map(document.getElementById(mapContainerID), myOptions);
        google.maps.event.addListener(polygonMap, "click", handlePolygonMapLeftClick);

        latlng = null;
        myOptions = null;
    }
    clearPolygonMap();
    mapContainerID = null;
};
/// <summary>Initializes polyline mode on the map.</summary>
var initializePolygonMapPolyline = function () {
    var polylineOptions = {
        strokeColor: polylineColour,
        strokeOpacity: 0.8,
        strokeWeight: 4
    };
    var polylineGhostOptions = {
        strokeColor: polylineGhostColour,
        strokeOpacity: 0.4,
        strokeWeight: 4
    };

    polyShape = new google.maps.Polyline(polylineOptions);
    polyShape.setMap(polygonMap);
    polylineGhost = new google.maps.Polyline(polylineGhostOptions);
    polylineGhost.setMap(polygonMap);

    polylineOptions = null;
    polylineGhostOptions = null;
};
/// <summary>Handle map clicks, only operates when in polyline mode when a new line is added</summary>
/// <param name="event" type="google.maps.event">event from the map</param>
var handlePolygonMapLeftClick = function (event) {
    if (polygonEditMode == 0) { // Only add new markers when clicking map if still in polyline mode
        if (event.latLng) {
            insertNewPolygonPolylineMarker(event.latLng);
        }
    }
    event = null;
};
/// <summary>Handle insertion of a new main marker, also creates associated mid markers and updates polyline/polygon path</summary>
/// <param name="newLatLng" type="google.maps.latLng">latLng of point to create main marker</param>
var insertNewPolygonPolylineMarker = function (newLatLng) {
    var newMarker = createPolygonPolylineMarker(newLatLng);
    polygonMarkers.push(newMarker);
    if (polygonMarkers.length != 1) {
        var newMidMarker = createPolygonPolylineMidMarker(newLatLng);
        polygonMidMarkers.push(newMidMarker);
        newMidMarker = null;
    }
    var polyLinePath = polyShape.getPath();
    polyLinePath.push(newLatLng);
    newMarker = null;
};
/// <summary>Adds a new main marker and associated icons and listeners</summary>
/// <param name="latlngPoint" type="google.maps.latLng">latLng of point to create main marker</param>
var createPolygonPolylineMarker = function (latlngPoint) {
    var imageStandard = new google.maps.MarkerImage(
		"/images/indicator.png",
		new google.maps.Size(13, 13),
		new google.maps.Point(0, 0),
		new google.maps.Point(7, 7)
	);
    var imageLink = new google.maps.MarkerImage(
		"/images/link.png",
		new google.maps.Size(13, 13),
		new google.maps.Point(0, 0),
		new google.maps.Point(7, 7)
	);
    var imageRollover = new google.maps.MarkerImage(
		"/images/rollover.png",
		new google.maps.Size(13, 13),
		new google.maps.Point(0, 0),
		new google.maps.Point(7, 7)
	);
    var imageDrag = new google.maps.MarkerImage(
		"/images/dragme.png",
		new google.maps.Size(13, 13),
		new google.maps.Point(0, 0),
		new google.maps.Point(7, 7)
	);
    var newMarker = new google.maps.Marker({
        position: latlngPoint,
        map: polygonMap,
        icon: imageStandard,
        draggable: true
    });

    // MouseOver Listener to show hover icon
    google.maps.event.addListener(newMarker, "mouseover", function () {
        if (polygonEditMode == 0) {
            for (var i = 0; i < polygonMarkers.length; i++) {
                if (polygonMarkers[i] == newMarker) {
                    if (i == 0 && polygonMarkers.length > 2) {
                        newMarker.setIcon(imageLink);
                    } else {
                        newMarker.setIcon(imageRollover);
                    }
                }
            }
            i = null;
        } else {
            newMarker.setIcon(imageRollover);
        }
    });

    // MouseOut Listener to revert back to standard icon
    google.maps.event.addListener(newMarker, "mouseout", function () {
        newMarker.setIcon(imageStandard);
    });

    google.maps.event.addListener(newMarker, "dragend", function () {
        newMarker.setIcon(imageStandard);
    });

    google.maps.event.addListener(newMarker, "dragstart", function () {
        newMarker.setIcon(imageDrag);
    });

    // Drag Listener to move polyline point and mid point markers associated with main marker
    google.maps.event.addListener(newMarker, "drag", function () {
        for (var i = 0; i < polygonMarkers.length; i++) {
            if (polygonMarkers[i] == newMarker) {
                //if (polygonEditMode == 0) {
                polyShape.getPath().setAt(i, newMarker.getPosition());
                //} else {
                //   polygonShape.getPath().setAt(i, newMarker.getPosition());
                //}

                movePolygonPolylineMidMarker(i);
                break;
            }
        }
        i = null;
    });

    // Click handler to remove marker and associated polyline point and mid markers
    // unless start marker clicked in which case convert polyline to polygon
    google.maps.event.addListener(newMarker, "click", function () {
        for (var i = 0; i < polygonMarkers.length; i++) {
            if (polygonMarkers[i] == newMarker) {
                if (i == 0 && polygonMarkers.length > 2) {
                    convertPolylineToPolygon();
                    break;
                } else {
                    newMarker.setMap(null);
                    polygonMarkers.splice(i, 1);
                    //if (polygonEditMode == 0) {
                    //} else
                    polyShape.getPath().removeAt(i);
                    removePolygonPolylineMidMarkers(i);
                    break;
                }
            }
        }
        i = null;
    });

    return newMarker;
};
/// <summary>Adds a new mid marker and associated icons and listeners</summary>
/// <param name="latlngPoint" type="google.maps.latLng">latLng of point to create mid marker</param>
var createPolygonPolylineMidMarker = function (latlngPoint) {
    var previousLatLng = polygonMarkers[polygonMarkers.length - 2].getPosition();

    var imageStandard = new google.maps.MarkerImage(
		"/images/indicator_trans.png",
		new google.maps.Size(13, 13),
		new google.maps.Point(0, 0),
		new google.maps.Point(7, 7)
	);
    var imageRollover = new google.maps.MarkerImage(
		"/images/rollover.png",
		new google.maps.Size(13, 13),
		new google.maps.Point(0, 0),
		new google.maps.Point(7, 7)
	);
    var imageDrag = new google.maps.MarkerImage(
		"/images/dragme.png",
		new google.maps.Size(13, 13),
		new google.maps.Point(0, 0),
		new google.maps.Point(7, 7)
	);
    var newMidMarker = new google.maps.Marker({
        position: new google.maps.LatLng(
			latlngPoint.lat() - (0.5 * (latlngPoint.lat() - previousLatLng.lat())),
			latlngPoint.lng() - (0.5 * (latlngPoint.lng() - previousLatLng.lng()))
		),
        map: polygonMap,
        icon: imageStandard,
        draggable: true
    });

    // MouseOver Listener to show hover icon
    google.maps.event.addListener(newMidMarker, "mouseover", function () {
        newMidMarker.setIcon(imageRollover);
    });

    // MouseOut Listener to revert back to standard icon
    google.maps.event.addListener(newMidMarker, "mouseout", function () {
        newMidMarker.setIcon(imageStandard);
    });

    // DragStart Listener to add points to ghost polyline
    google.maps.event.addListener(newMidMarker, "dragstart", function () {
        for (var i = 0; i < polygonMidMarkers.length; i++) {
            if (polygonMidMarkers[i] == newMidMarker) {
                newMidMarker.setIcon(imageDrag);
                var ghostPath = polylineGhost.getPath();
                ghostPath.push(polygonMarkers[i].getPosition()); // Do we need this? Surely it's replication
                ghostPath.push(polygonMidMarkers[i].getPosition());
                ghostPath.push(polygonMarkers[i + 1].getPosition());
                break;
            }
        }
        i = null;
    });

    // Drag Listener to move associated ghost polyline point
    google.maps.event.addListener(newMidMarker, "drag", function () {
        for (var i = 0; i < polygonMidMarkers.length; i++) {
            if (polygonMidMarkers[i] == newMidMarker) {
                polylineGhost.getPath().setAt(1, newMidMarker.getPosition());
                break;
            }
        }
        i = null;
    });

    /// DragEnd Listener to handle add a new main marker where the mid marker is positioned and then moving the mid marker to the position
    /// between the new main marker and the next main marker. A new mid marker is also created between the new main marker and the previous main marker.
    google.maps.event.addListener(newMidMarker, "dragend", function () {
        for (var i = 0; i < polygonMidMarkers.length; i++) {
            if (polygonMidMarkers[i] == newMidMarker) {
                newMidMarker.setIcon(imageStandard);
                var newPolyLinePoint = newMidMarker.getPosition();
                var startMarkerPoint = polygonMarkers[i].getPosition();
                var newMidPoint1 = new google.maps.LatLng(
					newPolyLinePoint.lat() - (0.5 * (newPolyLinePoint.lat() - startMarkerPoint.lat())),
					newPolyLinePoint.lng() - (0.5 * (newPolyLinePoint.lng() - startMarkerPoint.lng()))
				);
                var endMarkerPoint = polygonMarkers[i + 1].getPosition();
                var newMidPoint2 = new google.maps.LatLng(
					newPolyLinePoint.lat() - (0.5 * (newPolyLinePoint.lat() - endMarkerPoint.lat())),
					newPolyLinePoint.lng() - (0.5 * (newPolyLinePoint.lng() - endMarkerPoint.lng()))
				);
                // Add a new mid point marker
                var newMidMarker2 = createPolygonPolylineMidMarker(newMidPoint2);
                newMidMarker2.setPosition(newMidPoint2); //apply the correct position to the vmarker

                // create a new maker
                var newMarker = createPolygonPolylineMarker(newPolyLinePoint);
                polygonMarkers.splice(i + 1, 0, newMarker);
                polyShape.getPath().insertAt(i + 1, newPolyLinePoint);

                // move original mid point marker
                newMidMarker.setPosition(newMidPoint1);

                polygonMidMarkers.splice(i + 1, 0, newMidMarker2);

                polylineGhost.getPath().removeAt(2);
                polylineGhost.getPath().removeAt(1);
                polylineGhost.getPath().removeAt(0);
                newPolyLinePoint = null;
                startMarkerPoint = null;
                newMidPoint1 = null;
                endMarkerPoint = null;
                newMidPoint2 = null;
                newMidMarker2 = null;
                newMarker = null;
                break;
            }
        }
    });
    return newMidMarker;
};

/// <summary>Moves a mid marker and associated mid marker when a main marker moves</summary>
/// <param name="index" type="int">index of mid marker to move</param>
var movePolygonPolylineMidMarker = function (index) {
    var newLatLang = polygonMarkers[index].getPosition();
    if (index != 0) {
        var prevLatLng = polygonMarkers[index - 1].getPosition();
        polygonMidMarkers[index - 1].setPosition(new google.maps.LatLng(
			newLatLang.lat() - (0.5 * (newLatLang.lat() - prevLatLng.lat())),
			newLatLang.lng() - (0.5 * (newLatLang.lng() - prevLatLng.lng()))
		));
        prevLatLng = null;
    }
    if (index != polygonMarkers.length - 1) {
        var nextLatLng = polygonMarkers[index + 1].getPosition();
        polygonMidMarkers[index].setPosition(new google.maps.LatLng(
			newLatLang.lat() - (0.5 * (newLatLang.lat() - nextLatLng.lat())),
			newLatLang.lng() - (0.5 * (newLatLang.lng() - nextLatLng.lng()))
		));
        nextLatLng = null;
    }
    newLatLang = null;
    index = null;
};

/// <summary>Removes mid markers betweem main markers. The target mid marker is removed and the associated mid marker moved to be at the correct point</summary>
/// <param name="index" type="int">index of mid marker to remove</param>
var removePolygonPolylineMidMarkers = function (index) {
    if (polygonMarkers.length > 0) {//clicked marker has already been deleted
        if (index != polygonMarkers.length) {
            polygonMidMarkers[index].setMap(null);
            polygonMidMarkers.splice(index, 1);
        } else {
            polygonMidMarkers[index - 1].setMap(null);
            polygonMidMarkers.splice(index - 1, 1);
        }
    }
    if (index != 0 && index != polygonMarkers.length) {
        var prevLatLng = polygonMarkers[index - 1].getPosition();
        var newLatLang = polygonMarkers[index].getPosition();
        polygonMidMarkers[index - 1].setPosition(new google.maps.LatLng(
			newLatLang.lat() - (0.5 * (newLatLang.lat() - prevLatLng.lat())),
			newLatLang.lng() - (0.5 * (newLatLang.lng() - prevLatLng.lng()))
		));
        prevLatLng = null;
        newpos = null;
    }
    index = null;
};

/// <summary>Converts the initial polyline to a filled polygon</summary>
var convertPolylineToPolygon = function () {
    var polygonOptions = {
        fillColor: polygonFillColour,
        fillOpacity: 0.4,
        strokeColor: polygonBorderColour,
        strokeOpacity: 0.8,
        strokeWeight: 4
    };

    polyShape.setMap(null);
    polyShape = new google.maps.Polygon(polygonOptions);

    for (var i = 0; i < polygonMarkers.length; i++) {
        polyShape.getPath().setAt(i, polygonMarkers[i].getPosition());
    }

    polyShape.setMap(polygonMap);

    polygonEditMode = 1;
};
/// <summary>Clears the map of any markers, polygons and polylines then re-initialises it.</summary>
var clearPolygonMap = function () {
    if (polygonMarkers) {
        for (var i = 0; i < polygonMarkers.length; i++) {
            polygonMarkers[i].setMap(null);
        }
    }
    polygonMarkers.length = 0;

    if (polygonMidMarkers) {
        for (var i = 0; i < polygonMidMarkers.length; i++) {
            polygonMidMarkers[i].setMap(null);
        }
    }
    polygonMidMarkers.length = 0;

    clearPropertiesFromPolygonMap();

    if (polyShape) {
        polyShape.setMap(null);
    }

    if (polylineGhost) {
        polylineGhost.setMap(null);
    }

    polygonEditMode = 0;

    initializePolygonMapPolyline();
};
/// <summary>Saves the drawn polygon in a control as comma delimited values</summary>
/// <param name="sourceControl" type="String">The id of the control to store the values in</param>
var savePolygonMapPolygon = function (sourceControl) {
    if (polygonMarkers.length > 2) {
        var saveString = '';
        for (var i = 0; i < polygonMarkers.length; i++) {
            if (i > 0)
                saveString += ",";
            saveString += polygonMarkers[i].getPosition().lat().toString() + "," + polygonMarkers[i].getPosition().lng().toString();
        }
        $(sourceControl).value = saveString;
        return true;
    } else {
        $(sourceControl).value = '';
        return false;
    }
};
/// <summary>Loads a polygon from comma delimited latlngs in a control. Doesn't load if less than two points defined.</summary>
/// <param name="sourceControl" type="String">The id of the control to get the values from</param>
var loadPolygonMapPolygon = function (sourceControl) {
    var loadString = $(sourceControl).value;
    if (loadString) {
        var latlngArray = loadString.split(",");
        if (latlngArray.length > 2 && latlngArray.length % 2 == 0) {
            clearPolygonMap();
            //initializePolygonMapPolyline();
            convertPolylineToPolygon(sourceControl);

            for (var i = 0; i < latlngArray.length; i = i + 2) {
                var latlng = new google.maps.LatLng(latlngArray[i], latlngArray[i + 1]);
                insertNewPolygonPolylineMarker(latlng);
            }
        }
    }
};
// #region Debuging Search Only Remove in Release

var propertyMarkers = [];

var clearPropertiesFromPolygonMap = function () {
    if (propertyMarkers) {
        for (var i = 0; i < propertyMarkers.length; i++) {
            propertyMarkers[i].setMap(null);
        }
    }
    propertyMarkers.length = 0;
};
var plotPropertiesOnPolygonMap = function () {
    clearPropertiesFromPolygonMap();

    var jsonRequest = new Request.JSON({ url: getPolygonMapPropertyJSONURL(),
        onSuccess: function (ll, respText) {
            if (ll != 'null') {
                var llArray = [];
                llArray = ll;
                ll.each(function (item, index) {
                    latlng = new google.maps.LatLng(item.lat, item.lng);

                    var newMarker = new google.maps.Marker({
                        map: polygonMap,
                        position: latlng,
                        draggable: false,
                        title: "Property Available"
                    });
                    propertyMarkers.push(newMarker);
                });
            }
        }
    }).get();
};
var getPolygonMapPropertyJSONURL = function () {
    var SearchID = $('txtPolygonSearchID').value;
    if ((SearchID - 0) == SearchID && SearchID.length > 0) {
        return '/handlers/GetPropertyLatLngs.ashx?SearchID=' + SearchID;
    } else {
        return '/handlers/GetPropertyLatLngs.ashx';
    }
};
var plotSearchPolygonOnPolygonMapFromDB = function () {
    clearPolygonMap();
    convertPolylineToPolygon();

    var jsonRequest = new Request.JSON({ url: getPolygonMapSearchJSONURL(),
        onSuccess: function (ll, respText) {
            if (ll != 'null') {
                var llArray = [];
                llArray = ll;
                ll.each(function (item, index) {
                    latlng = new google.maps.LatLng(item.lat, item.lng);
                    insertNewPolygonPolylineMarker(latlng);
                });
            }
        },
        onError: function (errText, errVal) {
        }
    }).get();
};
var getPolygonMapSearchJSONURL = function () {
    var SearchID = $('txtPolygonSearchID').value;
    if ((SearchID - 0) == SearchID && SearchID.length > 0) {
        return '/handlers/GetPropertyLatLngs.ashx?SearchPolygon=true&SearchID=' + SearchID;
    } else {
        return '';
    }
};
// #endregion

// #endregion

// #region MultiSelect

var MultiSelect = new Class({
    Implements: [Options],

    options: {
        boxes: 'input[type=checkbox]', 	// checkbox selector
        labels: 'label', 				// label selector
        monitorText: ' selected', 	// monitor text (localization)
        zeroSelectedText: 'select one or more options', // RLB Added for more useful prompt
        containerClass: 'MultiSelect', 	// element container CSS class
        monitorClass: 'monitor', 	// monitor CSS class
        monitorActiveClass: 'active', // monitor open CSS class
        itemSelectedClass: 'selected', // list item selected CSS class
        itemHoverClass: 'hover'			// list item hover CSS class - usually we would use CSS :hover pseudo class, but we need this for keyboard navigation functionality
    },

    initialize: function (selector, options) {
        // set options
        this.setOptions(options);

        // set global action variables
        this.active = false;
        this.action = 'open';
        this.state = 'closed';

        // get elements array
        this.elements = document.getElements(selector);

        // off we go...
        this.elements.each(function (element) {
            this.buildMenu(element);
        }, this);
    },

    buildMenu: function (element) {
        // create closure
        var self = this;

        // add container class (for styling)
        element.addClass(self.options.containerClass);

        // create item instances
        var boxes = element.getElements(self.options.boxes);
        var labels = element.getElements(self.options.labels);

        // list container
        var list = new Element('ul', {
            'styles': { display: 'none' },
            'events': {
                'mouseenter': function () { self.action = 'open'; },
                'mouseleave': function () {
                    self.action = 'close';
                    self.itemHover(this, 'none');
                },

                'mousedown': function (e) { e.stop(); }, // stop text selection
                'selectstart': function () { return false; }, // stop IE text selection

                'keydown': function (e) {
                    if (e.key == 'esc') {
                        self.toggleMenu('close', monitor, this);
                    }
                    else if (e.key == 'down' || e.key == 'up') {
                        self.itemHover(this, e.key);
                    }
                }
            }
        });
        // list items
        boxes.each(function (box, i) {
            box.addEvents({
                'click': function (e) {
                    e.stop();
                },
                'keydown': function (e) {
                    if (e.key == 'space') {
                        self.active = true;
                        self.changeItemState(this.getParent(), this, monitor);
                    }
                    if (self.active && (e.key == 'down' || e.key == 'up')) {
                        self.changeItemState(this.getParent(), this, monitor);
                    }
                },
                'keyup': function (e) {
                    if (e.key == 'space') {
                        self.active = false;
                    }
                }
            });
            var label = labels[i];
            new Element('li', {
                'class': box.get('checked') ? self.options.itemSelectedClass : '',
                'events': {
                    'mouseenter': function () {
                        if (self.active === true) {
                            self.changeItemState(this, box, monitor);
                        }
                        self.itemHover(list, this);
                    },
                    'mousedown': function () {
                        self.active = true;
                        self.changeItemState(this, box, monitor);
                    }
                }
            }).adopt([box, label]).inject(list);
        });
        // list monitor
        var monitor = new Element('div', {
            'class': self.options.monitorClass,
            'html': '<div><div>' + self.changeMonitorValue(list) + '</div></div>',
            'tabindex': 0,
            'events': {
                'mouseenter': function () { self.action = 'open'; },
                'mouseleave': function () { self.action = 'close'; },
                'click': function () {
                    if (this.hasClass(self.options.monitorActiveClass)) {
                        self.toggleMenu('close', monitor, list);
                    }
                    else {
                        self.toggleMenu('open', monitor, list);
                    }
                },
                'keydown': function (e) {
                    if (e.key == 'space' || e.key == 'down' || e.key == 'up') {
                        self.action = 'close';
                        self.toggleMenu('open', monitor, list);
                    }
                },

                'mousedown': function (e) { e.stop(); }, // stop text selection
                'selectstart': function () { return false; } // stop IE text selection
            }
        });
        // 'global' events
        document.addEvents({
            'mouseup': function () { self.active = false; },
            'click': function () {
                if (self.action == 'close') {
                    self.toggleMenu('close', monitor, list);
                }
            },
            'keydown': function (e) {
                if (e.key == 'esc') {
                    self.toggleMenu('close', monitor, list);
                    self.itemHover(list, 'none');
                }
                if (self.state == 'opened' && (e.key == 'down' || e.key == 'up')) {
                    e.stop();
                }
            }
        });
        // replace element content
        element.empty().adopt([monitor, list]);
    },

    append: function (selector) {
        var elements = document.getElements(selector);
        this.elements.combine(elements);

        elements.each(function (element) {
            this.buildMenu(element);
        }, this);
    },

    changeItemState: function (item, checkbox, monitor) {
        if (item.hasClass(this.options.itemSelectedClass)) {
            item.removeClass(this.options.itemSelectedClass);
            checkbox.set('checked', false).focus();
        }
        else {
            item.addClass(this.options.itemSelectedClass);
            checkbox.set('checked', true).focus();
        }
        // Just for Jackie Stanley Site!
        jsUPStoreSearch();
        monitor.set('html', '<div><div>' + this.changeMonitorValue(item.getParent()) + '</div></div>');
    },

    changeMonitorValue: function (list) {
        var text = list.getElements(this.options.boxes).filter(function (box) {
            return box.get('checked');
        }).length;
        if (text == '0') {
            return this.options.zeroSelectedText;
        }
        else {
            return text + this.options.monitorText;
        }

        //return text;
    },

    itemHover: function (list, select) {
        var current = list.getElement('li.' + this.options.itemHoverClass);

        switch (select) {
            case 'down':
                if (current && (sibling = current.getNext())) current.removeClass(this.options.itemHoverClass);
                else this.itemHover(list, 'last');
                break;
            case 'up':
                if (current && (sibling = current.getPrevious())) current.removeClass(this.options.itemHoverClass);
                else this.itemHover(list, 'first');
                break;
            case 'none':
                list.getElements('li.' + this.options.itemHoverClass).removeClass(this.options.itemHoverClass);
                break;
            case 'first':
                var sibling = list.getFirst();
                break;
            case 'last':
                var sibling = list.getLast();
                break;
            default:
                if (current) current.removeClass(this.options.itemHoverClass);
                var sibling = select;
                break;
        }

        if (sibling)
            sibling.addClass(this.options.itemHoverClass).getElement(this.options.boxes).focus();
    },

    toggleMenu: function (toggle, monitor, list) {
        if (toggle == 'open') {
            monitor.addClass(this.options.monitorActiveClass);
            list.setStyle('display', '');
            this.itemHover(list, 'first');

            this.state = 'opened';
        }
        else {
            // close all MultiSelect menus
            this.elements.getElement('div.monitor').removeClass(this.options.monitorActiveClass);
            this.elements.getElement('ul').setStyle('display', 'none');

            this.action = 'open';
            this.state = 'closed';
        }

        if (list.getScrollSize().y > (list.getStyle('max-height').toInt() ? list.getStyle('max-height').toInt() : list.getStyle('height').toInt()))
            list.setStyle('overflow-y', 'scroll');
    }
});

// #endregion

// #region  DOM Ready Calls

window.addEvent('domready', function () {
    // Load Carousels
    if ($('homepanel') != null) {
        ld();
    }
    if ($('bottomcarouselwrapper') != null) {
        pb_ld();
    }

    // Utility Panel
    jsUPSetVisibility('');
    jsUPRestoreSearch();
    jsUPRestoreRegister();
    var myMultiSelect = new MultiSelect('.MultiSelectOutlook', { zeroSelectedText: 'show all characteristics' });
    var myMultiSelect2 = new MultiSelect('.MultiSelectPropertyType', { zeroSelectedText: 'show all types' });
    var myMultiSelect3 = new MultiSelect('.MultiSelectRegisterOutlook', { zeroSelectedText: 'include all types' });
    var loarUtilityImage = Asset.images(utiliyPanelPreLoadImages);
    // setup geocoder for use
    geocoder = new google.maps.Geocoder();

    setupDrawASearchIndicator();
    // General
    applyTextBoxPrompts();

    bindLightbox();
});

// #endregion

