﻿var mapID = document.getElementById("map");
var sideBarID = document.getElementById("sidebar");

/**
* A general helper function for creating html elements. <div> as default element type
* @author Esa 2008 
* used for infowindows and sidebar
*/
function createElem(opt_className, opt_html, opt_tagName) {
    var tag = opt_tagName || "div";
    var elem = document.createElement(tag);
    if (opt_html) elem.innerHTML = opt_html;
    if (opt_className) elem.className = opt_className;
    return elem;
}

/**
* sidebar with categories
* @author Esa 2008
*/
function SideBar(block_element, opt_options) {
    var opts = opt_options || {};
    this.division = createElem("sidebar-contents");
    block_element.appendChild(this.division);
    this.show = function() { this.division.style.display = "block" };
    this.hide = function() { this.division.style.display = "none" };
    this.cats = [];

    this.addEntry = function(point, index, opt_options) {
        var opts = opt_options || {};
        var iLabel = opts.iLabel || 2;
        var label = createElem("sidebar-entry", point.textArray[iLabel], "a");
        label.href = "#";
        label.style.display = "block";
        label.onclick = function() { cluster.triggerClick(index); return false }; //x-browser
        label.onfocus = function() { cluster.triggerClick(index); return false };
        this.division.appendChild(label);
        GEvent.addListener(point.marker, 'click', function() { label.focus(); return false });
    }
    this.clear = function() {
        while (this.division.firstChild) {
            this.division.removeChild(this.division.firstChild);
        }
    }
}

/**
* category to a sidebar
* @author Esa 2008
*/
function BarCategory(sideBar, catName, opt_options) {
    var me = this;
    var opts = opt_options || {};
    me.division = createElem("sidebar-cat");
    var cssClasses = "sidebar-cat-header cat-header-" + catName;
    var cat = createElem(cssClasses);
    me.pin = createElem("sidebar-cat-image", null, "img");
    me.pin.src = opts.icon.image;
    cat.appendChild(me.pin);
    var check = createElem("sidebar-cat-check", null, "input");
    me.header = cat;
    check.type = "checkbox";
    check.checked = opts.checked || false;
    cat.appendChild(check);
    var checkLabel = createElem("sidebar-cat-label", catName, "span");
    cat.appendChild(checkLabel);
    me.show = function() {
        me.division.style.display = "block";
        me.pin.style.visibility = "visible";
    }
    me.hide = function() {
        me.division.style.display = "none";
        me.pin.style.visibility = "hidden";
    }
    me.hilight = function() { me.header.className = cssClasses + "  hilight-cat-header" };
    me.lolight = function() { me.header.className = cssClasses };
    sideBar.division.appendChild(cat);
    sideBar.division.appendChild(me.division);
    sideBar.cats[catName] = me;
    me.markers = [];
    me.showMarkers = function() {
    for (var i = 0; i < me.markers.length; i++) {
            me.markers[i].show();
        }
    }
    me.hideMarkers = function() {
        for (var i = 0; i < me.markers.length; i++) {
            me.markers[i].hide();
            me.markers[i].closeInfoWindow();
        }
    }
    function update() {
        if (check.checked) {
            me.show();
            me.showMarkers();
            me.hilight();
        } else {
            me.hide();
            me.hideMarkers();
            me.lolight();
        }
        cluster.refresh();
    };
    check.onclick = update;
    me.update = update;
    me.check = check;

    me.addEntry = function(point, index, opt_options) {
        var opts = opt_options || {};
        me.markers.push(point.marker);
        var iLabel = opts.iLabel || 2;
        var label = createElem("sidebar-entry", point.textArray[iLabel], "a");
        label.href = "#";
        label.style.display = "block";
        label.onclick = function() { cluster.triggerClick(index); return false }; //x-browser
        label.onfocus = function() { cluster.triggerClick(index); return false };
        me.division.appendChild(label);
        GEvent.addListener(point.marker, 'click', function() { label.focus(); return false });
    }
    me.clear = function() {
        while (me.division.firstChild) {
            me.division.removeChild(me.division.firstChild);
        }
    }
}


/**
* Marker icon
*/
function tinyImage(opt_color, opt_preload) {
    var color = opt_color || "red";
    var src_ = "http://labs.google.com/ridefinder/images/mm_20_" + color + ".png";
    if (opt_preload) {
        var preImage = new Image();
        preImage.src = src_;
    }
    return src_;
}
function tinyIcon(opt_color) {
    var tiny = new GIcon();
    tiny.image = tinyImage(opt_color);
    tiny.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
    tiny.iconSize = new GSize(12, 20);
    tiny.shadowSize = new GSize(22, 20);
    tiny.iconAnchor = new GPoint(6, 20);
    tiny.infoWindowAnchor = new GPoint(5, 1);
    tiny.imageMap = [4, 0, 0, 4, 0, 7, 3, 11, 4, 19, 7, 19, 8, 11, 11, 7, 11, 4, 7, 0];
    tiny.transparent = "tiny_transparent.png";
    return tiny;
}
//Preload loop
//Electronics freaks  know the numbering scheme
var icons = ["black", "brown", "red", "orange", "yellow", "green", "blue", "purple", "gray", "white"];
for (var color in icons) {
    tinyImage(icons[color], true);
}


/**
* GMap2.showBounds() method. Fit bounds to viewport with paddings.
* @ author Esa 2008
* @ param bounds_ GLatLngBounds()
* @ param opt_options Optional options object {top, right, bottom, left, save}
*/
GMap2.prototype.showBounds = function(bounds_, opt_options) {
    var opts = opt_options || {};
    opts.top = opt_options.top * 1 || 0;
    opts.left = opt_options.left * 1 || 0;
    opts.bottom = opt_options.bottom * 1 || 0;
    opts.right = opt_options.right * 1 || 0;
    opts.save = opt_options.save || true;
    opts.disableSetCenter = opt_options.disableSetCenter || false;
    var ty = this.getCurrentMapType();
    var port = this.getSize();
    if (!opts.disableSetCenter) {
        var virtualPort = new GSize(port.width - opts.left - opts.right,
                            port.height - opts.top - opts.bottom);
        this.setZoom(ty.getBoundsZoomLevel(bounds_, virtualPort));
        var xOffs = (opts.left - opts.right) / 2;
        var yOffs = (opts.top - opts.bottom) / 2;
        var bPxCenter = this.fromLatLngToDivPixel(bounds_.getCenter());
        var newCenter = this.fromDivPixelToLatLng(new GPoint(bPxCenter.x - xOffs, bPxCenter.y - yOffs));
        this.setCenter(newCenter);
        if (opts.save) this.savePosition();
    }
    var portBounds = new GLatLngBounds();
    portBounds.extend(this.fromContainerPixelToLatLng(new GPoint(opts.left, port.height - opts.bottom)));
    portBounds.extend(this.fromContainerPixelToLatLng(new GPoint(port.width - opts.right, opts.top)));
    return portBounds;
}


/**
* Map
*/
_mPreferMetric = true;                                 //to make size sure for IE too
var map = new GMap2(mapID, { size: new GSize(556, 500) });
map.setCenter(new GLatLng(0, 0), 9);
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
map.addControl(new GScaleControl());
var marker, markersArray = [];
var cluster;

/**
* parseCsv()
* @return an array of GLatLng() objects
* @param opt_options object {lat, lng} integers defining the csv cells of coordinates (default: {lat:1, lng:0})
* @author Esa 2008
*/
String.prototype.parseCsv = function(opt_options) {
    var results = [];
    var opts = opt_options || {};
    var iLat, iLng;
    isNaN(opts.lat) ? iLat = 1 : iLat = opts.lat;  // defaults 
    isNaN(opts.lng) ? iLng = 0 : iLng = opts.lng;  // fixed 2009
    var lines = this.split("\n");
    for (var i = 0; i < lines.length; i++) {
        var blocks = lines[i].split('"');
        //finding commas inside quotes. Replace them with '::::'
        for (var j = 0; j < blocks.length; j++) {
            if (j % 2) {
                blocks[j] = blocks[j].replace(/,/g, '::::');
            }
        }  //@author Esa 2008, keep this note.
        lines[i] = blocks.join("");
        var lineArray = lines[i].split(",");
        var lat = parseFloat(lineArray[iLat]);
        var lng = parseFloat(lineArray[iLng]);
        var point = new GLatLng(lat, lng);
        //after splitting by commas, we put hidden ones back
        for (var cell in lineArray) {
            lineArray[cell] = lineArray[cell].replace(/::::/g, ',');
        } //corrupted line step-over
        if (!isNaN(lat + lng)) {
            point.textArray = lineArray;
            results.push(point);
        }
    }
    return results;
}


/**
* Create the markers, with  infowindow.
* Create sidebar categories and entries.
*/

var bounds = new GLatLngBounds();

GMap2.prototype.populate = function(points, options) {
    var opts = options || {};
    var noCat = true;
    if (opts.cat || opts.iCat) noCat = false;
    var catName = opts.cat || "";
    var bar = opts.sidebar;
    var myCat;
    var newCats = [];
    for (var i = 0; i < points.length; i++) {
        if (opts.iCat) { // category from file contents
            catName = points[i].textArray[opts.iCat];
        }
        var theIcon = opts.icon || CAT_ICONS[catName] || CAT_ICONS["DEFAULT_ICON"];
        if (!bar.cats[catName] && !noCat) { // create a category if not found
            myCat = new BarCategory(bar, catName, { icon: theIcon });
            newCats.push(myCat);
        }
        var iLabel = opts.iLabel || 2;
        var label = points[i].textArray[iLabel];
        points[i].marker = new GMarker(points[i], { title: label, icon: theIcon });
        markersArray.push(points[i].marker);

        bounds.extend(points[i]); // this must be considered
        createInfoWindow(points[i], opts);
        if (noCat) {
            bar.addEntry(points[i], i, opts);
        } else {
            myCat.addEntry(points[i], i, opts);
        }
    }
    cluster = new ClusterMarker(map, { markers: markersArray });
    cluster.fitMapToMarkers();

    myCat.check.checked = opts.checked || false;
    myCat.update();
    for (var i = 0; i < newCats.length; i++) {
        newCats[i].check.checked = opts.checked || false;
        newCats[i].update();
    }
    var paddings = { top: 30, right: 10, bottom: 10, left: 50 };
    this.showBounds(bounds, paddings);
}



/**
* create infowindow
*/
function createInfoWindow(point, opt_options) {
    var opts = opt_options || {};
    var start = opts.iLabel || 2;
    var iwNode = createElem("info-window");
    var iwRows = [];

    var header = createElem("iw-header", point.textArray[3], "h2");
    iwNode.appendChild(header);

    var address = createElem("iw-address", point.textArray[4], "p");
    iwNode.appendChild(address);
    
    if (point.textArray[5]) {
        var website = createElem("iw-website", "Website", "a");
        website.href = "http://" + point.textArray[5];
        website.target = "_blank";
        iwNode.appendChild(website);
    }

    if (point.textArray[6]) {
        var h2 = createElem("", "Available activities:", "h3");
        iwNode.appendChild(h2);
        
        var immpages = point.textArray[6].split("|");
        var ul = createElem("iw-list","", "ul");
        
        for (i = 0; i < immpages.length; i++) {
            var pDetails = immpages[i].split(',');

            var pUrl = pDetails[0];
            var pTitle = pDetails[1];
            
            var li = createElem("iw-listitem", "<a href=\""+ pUrl+"\"\>"+pTitle+"</a>", "li");
            ul.appendChild(li);
        }

        iwNode.appendChild(ul);
    }
      
    point.marker.bindInfoWindow(iwNode, { maxWidth: 300 });
}


/**
* This function triggers the downloading and parsing of a selected text file
* marker, sidebar and infowindow data is extracted from the file
*/

var myBar = new SideBar(sideBarID);

function ajaxLoad(textFile, opt_options) {
    var opts = opt_options || {};
    opts.sidebar = myBar;
    var process = function(material) {
        var entries = material.parseCsv(opts);  // fixed 2009
        map.populate(entries, opts);
    }
    GDownloadUrl(textFile, process);
}


/**
* Postcode search to place circle on map
*/

// pan and zoom to fit
var bounds = new GLatLngBounds();
function fit() {
    map.panTo(bounds.getCenter());
    map.setZoom(map.getBoundsZoomLevel(bounds));
}

// Geo
var geocoder = new GClientGeocoder();
function showAddress(address) {
    geocoder.getLatLng(address, function(point) {
        if (!point) {
            document.getElementById('address').style.color = 'red';
        }
        else {
            draw(point);
            map.panTo(point);
            document.getElementById('address').style.color = 'black';
        }
    })
}

// calling circle drawing function
var poly;
function draw(pnt) {

    // remove previous circle if it exists
    if (poly) {
        map.removeOverlay(poly);
    }
    
    bounds = new GLatLngBounds();
    var givenRad = 1 * 1;
    var givenQuality = 40 * 1;
    var centre = pnt || map.getCenter()
    drawCircle(centre, givenRad, givenQuality);
    fit();
}

function drawCircle(center, radius, nodes, liColor, liWidth, liOpa, fillColor, fillOpa) {

    // calculating km/degree
    var latConv = center.distanceFrom(new GLatLng(center.lat() + 0.1, center.lng())) / 100;
    var lngConv = center.distanceFrom(new GLatLng(center.lat(), center.lng() + 0.1)) / 100;

    // Loop 
    var points = [];
    var step = parseInt(360 / nodes) || 10;
    for (var i = 0; i <= 360; i += step) {
        var pint = new GLatLng(center.lat() + (radius / latConv * Math.cos(i * Math.PI / 180)), center.lng() +
	(radius / lngConv * Math.sin(i * Math.PI / 180)));
        points.push(pint);
        bounds.extend(pint); //this is for fit function
    }
    points.push(points[0]); // Closes the circle, thanks Martin
    fillColor = fillColor || liColor || "#0055ff";
    liWidth = liWidth || 2;
    poly = new GPolygon(points, liColor, liWidth, liOpa, fillColor, fillOpa);
    map.addOverlay(poly);
}

var CAT_ICONS = [];
CAT_ICONS["DEFAULT_ICON"] = tinyIcon("red");
/*
CAT_ICONS["Introduction"] = tinyIcon("red");
CAT_ICONS["Code"] = tinyIcon("green");
CAT_ICONS["Craters"] = tinyIcon("gray");
CAT_ICONS["Airports"] = tinyIcon("blue");
CAT_ICONS["McDonald's"] = tinyIcon("yellow");
CAT_ICONS["Towns"] = tinyIcon("purple");
*/


window.onload = function() {
    ajaxLoad("/plugins/HC_GoogleMaps/MarkerData.aspx?cat=all", { iCat: 2, checked: false, iLabel: 3 });
}
window.onunload = function() {
    GUnload();
}

/**
* Target group switcher
*/

document.getElementById("Select").onchange = function() {
    var index = this.selectedIndex;
    var value = this.options[index].value;
    
    // reset map before loading
    map.clearOverlays();
    sideBarID.innerHTML = "";
    myBar = new SideBar(sideBarID);

    ajaxLoad("/plugins/HC_GoogleMaps/MarkerData.aspx?cat=" + value, { iCat: 2, checked: false, iLabel: 3 });
}
