/* Minification failed. Returning unminified contents.
(187,40-41): run-time error JS1014: Invalid character: `
(187,41-42): run-time error JS1195: Expected expression: <
(187,87-88): run-time error JS1195: Expected expression: &
(187,93-94): run-time error JS1195: Expected expression: <
(187,138-139): run-time error JS1014: Invalid character: `
(188,36-37): run-time error JS1014: Invalid character: `
(188,37-38): run-time error JS1195: Expected expression: <
(188,65-66): run-time error JS1195: Expected expression: <
(188,70-71): run-time error JS1014: Invalid character: `
(191,44-45): run-time error JS1014: Invalid character: `
(191,70-71): run-time error JS1004: Expected ';': {
(191,100-101): run-time error JS1014: Invalid character: `
(193,44-45): run-time error JS1014: Invalid character: `
(193,45-46): run-time error JS1195: Expected expression: <
(193,95-96): run-time error JS1195: Expected expression: >
(193,101-102): run-time error JS1197: Too many errors. The file might not be a JavaScript file: >
(158,1-54): run-time error JS1301: End of file encountered before function is properly closed: function getDistricts(long, lat, address, clickedMap)
(193,103-104): run-time error JS1004: Expected ';': {
(193,120-121): run-time error JS1195: Expected expression: <
(193,121-122): run-time error JS1197: Too many errors. The file might not be a JavaScript file: /
 */
var google_map, autocomplete, marker, infowindow, geocoder;

function initialize_map() {
    var myLatlng = new google.maps.LatLng(42.262284, -71.802063); // Center of Massachusetts State Plane Bounding Box
    var location = document.getElementById('location');

    var myOptions = {
        zoom: 9,
        center: myLatlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        zoomControlOptions: { style: google.maps.ZoomControlStyle.LARGE },
        mapTypeControl: false,
        fullscreenControl: false,
        streetViewControl: false,
    }

    google_map = new google.maps.Map(document.getElementById('map_canvas'), myOptions);

    // initialize geocoder
    geocoder = new google.maps.Geocoder;

    // initialize autocomplete input control and bind to what is visible in map
    autocomplete = new google.maps.places.Autocomplete(location);

    autocomplete.radius = 50000;
    // limit results to US
    autocomplete.setComponentRestrictions({ 'country': ['us'] });
    autocomplete.types = ['geocode']; // seem to be getting establishment results anyway
    autocomplete.setFields(['address_components', 'geometry', 'formatted_address']);

    // add event listener to map
    google.maps.event.addListener(google_map, 'click', clickMapOrData);
    // add event listener to data layer
    google_map.data.addListener('click', clickMapOrData);

    // add the input and legend controls
    google_map.controls[google.maps.ControlPosition.TOP_CENTER].push(location);
    google_map.data.setStyle(function (district) {
        var styleObject;
        if (district.j.branch == 'Senate' || district.j.branch == 'NewSenate') {
            styleObject = {
                fillOpacity: 0.03,
                fillColor: "#0000ff",
                strokeColor: "#0000ff",
                strokeWeight: 2,
                strokeOpacity: .5
            };
        } else if (district.j.branch == 'House' || district.j.branch == 'NewHouse') {
            styleObject = {
                fillOpacity: 0.06,
                fillColor: "#ff143C",
                strokeColor: "#ff143C",
                strokeWeight: 1,
                strokeOpacity: .5
            };
        } else {
            styleObject = {
                fillOpacity: 0.01,
                fillColor: "#163b1d",
                strokeColor: "#163b1d",
                strokeWeight: 2,
                strokeOpacity: .5
            };
        }
        return styleObject;
    });

    // on start up legend and input are hidden -- avoid bounce by showing only when map is ready
    google.maps.event.addListenerOnce(google_map, 'tilesloaded', function () {
        location.style.display = "block";
    });

    // initialize info window
    infowindow = new google.maps.InfoWindow();

    // initialize marker bound to map
    marker = new google.maps.Marker({
        map: google_map
    });
    // set click listener on marker
    marker.addListener('click', function () {
        infowindow.open(google_map, marker);
    });

    //initialize the listener on the autocomplete 
    autocomplete.addListener('place_changed', goToPlace);

    // if the location value exists initially load to that location
    if ($(location).val() != undefined && $(location).val() != null && $(location).val() != "") {
        geocoder.geocode({ 'address': $(location).val() }, function (results, status) {
            $(location).val('');
            if (results && results.length > 0) {
                loadPlace(results[0]);
            }
        });
    }   
}

function goToPlace() {
    cleanup();
    // get the place from the autocomplete
    var place = autocomplete.getPlace();
    loadPlace(place);
}

function loadPlace(place) {
    // locate and show marker
    marker.setPosition(place.geometry.location); // not setting place property of marker, just location, to avoid conflict with click listener
    marker.setVisible(true);

    // with address as town, return if not an MA address
    if ('massachusetts' != extractComponentType(place.address_components, 'administrative_area_level_1')) {
        infowindow.setContent('<div id="content">No district available &mdash; only Massachusetts addresses supported.</div>')
        google_map.setCenter(marker.getPosition());
    }
    infowindow.open(google_map, marker);

    // get the districts containing the place 
    getDistricts(place.geometry.location.lng(), place.geometry.location.lat(), trimFormattedAddress(place.formatted_address), false);
}

function clickMapOrData(e) {
    cleanup();
    // locate and show marker
    google_map.panTo(e.latLng);
    marker.setPosition(e.latLng);
    marker.setVisible(true);
    infowindow.open(google_map, marker); // showing loader
    // get the districts containing the new lat lan 
    reverseGeocode(e.latLng.lng(), e.latLng.lat()).then(function (result) { getDistricts(e.latLng.lng(), e.latLng.lat(), result, true);})
}

// attempt reverseGeoCode on click of map
function reverseGeocode(lng, lat) {
    return new Promise(function (resolve) {
        geocoder.geocode({ location: { lat: lat, lng: lng } }, function (results, status) {
            if (status === 'OK') {
                if (results.length) {
                    // swap in this result into window content in place of lat lon
                    let formattedAddress = '';

                    // Filter out plus code and route type
                    for (var i = 0; i < results.length; i++) {
                        if (!results[i].types.find(function (x) { return x === 'plus_code' || x === 'route'; })) {
                            formattedAddress = results[i].formatted_address;
                            break;
                        }
                    }

                    resolve(trimFormattedAddress(formattedAddress));
                }
            }
            resolve('at Latitude ' + lat.toFixed(3) + ', Longitude ' + lng.toFixed(3));
        });
    });
}

function getDistricts(long, lat, address, clickedMap) {
    var origin = window.location.href;
    var isRedistrictingOrigin = origin.toLowerCase().indexOf('redistricting') > 0;
    $.ajax({
        url: "/Legislators/GetDistrictByLatLong",
        type: 'Get',
        cache: false,
        data: {
            latitude: lat,
            longitude: long,
            isDistrictSearch: isRedistrictingOrigin,
        },
        success: function (response) {
            var districts = response.districts;
            var congressionalHearing = response.congressionalHearing;
            var content = '<div class="h5">'+ address + '</div>';
            var bounds = new google.maps.LatLngBounds();
            if (districts.length) {
                districts.forEach(function (district) {
                    var feature = JSON.parse(district.FeatureJson);
                    feature.properties.branch = district.Branch;                    
                    //congressional is not used currently
                    if (district.Branch === 'Congressional' || district.Branch == "NewCongressional") {
                        var url = district.Description;
                        var anchorText = district.Congressperson;
                        var eventUrl = '/Redistricting/Index#upcomingHearings';
                        var eventAnchorText = 'See upcoming redistricting hearings'
                        content += '<div class="legDetails">';
                        if (district.Branch !== "NewCongressional")
                            content += `<a target="_blank" href="${url}">${anchorText}&nbsp;<span class="fa fa-external-link"></span></a>`;
                        content += `<em>${district.DistrictName}</em>`;
                        if (district.Branch !== "NewCongressional") {
                            if (congressionalHearing != null) {
                                eventUrl = `/Events/Hearings/Detail/${congressionalHearing.EventId}`;
                                eventAnchorText = congressionalHearing.Description;
                                content += `<span>Hearing: <a target="_blank" href=${eventUrl}><span>${eventAnchorText}</span></a></span>`
                            }
                            else {
                                content += `<a target="_blank" href=${eventUrl}><div>${eventAnchorText}</div></a>`;
                            }
						}                      
                        content += '</div>'
                        // need to change it to be unique from the other branches otherwise it'll overwrite it
                        feature.id = "c" + feature.id;
                    } else if (district.Branch === "NewSenate" || district.Branch === "NewHouse") {
                        var branchDisplay = district.Branch === "NewSenate" ? "Senate" : "House";
                        content +=
                            '<div class="legDetails">' +
                            `<span>${branchDisplay}</span >` +
                            `<em>${district.DistrictName}</em>` +
                            '</div> ';
                        // need to change it to be unique from the other branches otherwise it'll overwrite it
                        feature.id = branchDisplay + feature.id;
                    } else {
                        var url = district.UserMemberCode ? ('/Legislators/Profile/' + district.UserMemberCode) : ('/Legislators/District/' + district.DistrictCode);
                        content +=
                            '<div class="legDetails">' +
                                `<a target="_blank" href="${url}">${district.LegislatorDisplayName}</a >` + 
                                `<em>${district.DistrictName}</em>` + 
                            '</div> ';
                    }
                    google_map.data.addGeoJson(feature);

                });
                infowindow.setContent(content);
                if (!clickedMap) {
                    google_map.panTo({ lat, lng: long})
                }
                $('#location').addClass("legislatorResults");
            }
            else {
                infowindow.setContent('<div id="content">No district available &mdash; only Massachusetts addresses supported.</div>')
            }
        },
        error: function (error) {
            var content = '<div class="h5">' + address + '</div>';
            infowindow.setContent(content);
            if (!clickedMap) {
                google_map.panTo({ lat, lng: long })
            }
            $('#location').addClass("legislatorResults");
        }
    });
}

// after get district and add to data layer, center map around the district
function centerMapOnPolygon(feature, bounds) {
    var geometry = feature.geometry;
    var geometryType = geometry.type;

    if ('Polygon' == geometryType) {
        extendBoundsToPolygon(geometry.coordinates, bounds);
    } else {
        // mulipolygon case -- iterate across polygons, expanding minimum bounding rectangle
        geometry.coordinates.forEach(function (polygon) {
            extendBoundsToPolygon(polygon, bounds);
        });
    }
}

// determine minimum bounding rectangle for polygon
function extendBoundsToPolygon(polygon, bounds) {
    polygon.forEach(function (ring) {
        ring.forEach(function (vertex) {
            vertex = new google.maps.LatLng(vertex[1], vertex[0]);
            bounds.extend(vertex);
        });
    });
}

function cleanup() {
    // close window -- repoint to window loading
    $('#location').val('');
    infowindow.close()
    infowindow.setContent('<div id="infowindow-loader">Loading . . .</div>');
    google_map.data.forEach(function (feature) {
        google_map.data.remove(feature);
    });
}

// function to extract component value of component type from places address_components return 
// https://developers.google.com/maps/documentation/geocoding/start#Types for valid types ( note that limiting search to united states)
function extractComponentType(components, type) {
    var countAddress_components = components.length,
        countAddress_componentTypes = 0;
    for (var i = 0; i < countAddress_components; i++) {
        if (components[i].types) {
            if (countAddress_componentTypes = components[i].types.length) {
                for (var j = 0; j < countAddress_componentTypes; j++) {
                    if (type == components[i].types[j]) {
                        return components[i].long_name.toLowerCase();
                    }
                }
            }
        }
    }
}

function trimFormattedAddress(formattedAddress) {
    return formattedAddress.replace(/, USA$/, '');
};
