/**************************************************
* Render Feature
**************************************************/
function initQuery(featureServiceName, featureServiceLayerId, featureServiceOutField, featureServiceReturnGeometry, featureServiceWhereClause, callbackFunction)
{
    var layerIds = featureServiceLayerId.split("-");
    //build query
    queryTask = new esri.tasks.QueryTask(g_ArcGISURLStub + "rest/services/Maps/" + featureServiceName + "/MapServer/" + layerIds[0] + "?token=" + g_mapToken);
    //build query filter
    query = new esri.tasks.Query();
    query.outFields = [featureServiceOutField];
    query.returnGeometry = featureServiceReturnGeometry;
    query.where = featureServiceWhereClause;
    queryTask.execute(query, callbackFunction);
}

function initFeature()
{
    if (map.graphics != null && gFeature != null)
        map.graphics.remove(gFeature);
    // remove any extra services
    if (gFeatureServiceLayer != null)
        map.removeLayer(gFeatureServiceLayer);
    // remove legend if necessary
    dojo.byId("legend").innerHTML = "";

    switch(gFeatureName)
    {
        case "":
            var featureSelect = dojo.byId("features");
            if (featureSelect != null)
                featureSelect.disabled = false;
            break;
        case "ALL":
            // add in extra service
            gFeatureServiceLayer = new esri.layers.ArcGISDynamicMapServiceLayer(g_ArcGISURLStub + "rest/services/Maps/" + gServiceName + "/MapServer?token=" + g_mapToken);
            map.addLayer(gFeatureServiceLayer);
            // turn appropriate layer on
            dojo.connect(gFeatureServiceLayer, "onLoad", showLayer);
            dojo.connect(gFeatureServiceLayer, "onUpdate", hideLoading);
            break;
        default: // will be the feature name e.g. "Tridion school"
            gFeatureServiceLayer = new esri.layers.ArcGISDynamicMapServiceLayer(g_ArcGISURLStub + "rest/services/Maps/" + gServiceName + "/MapServer?token=" + g_mapToken);
            map.addLayer(gFeatureServiceLayer);
            // turn appropriate layer on
            dojo.connect(gFeatureServiceLayer, "onLoad", showLayer);
            dojo.connect(gFeatureServiceLayer, "onUpdate", hideLoading);
            // initiate query to get details of particular feature
            var fieldNames = gFieldName.split(",");
            var fieldValues = gFeatureName.split("*");
            var whereClause = "";
            for (var i = 0; i < fieldNames.length; i++)
            {
                if (whereClause == "")
                    whereClause = fieldNames[i] + "='" + fieldValues[i].replace("'", "''") + "'";
                else
                    whereClause += " AND " + fieldNames[i] + "='" + fieldValues[i].replace("'", "''") + "'";
            }
            initQuery(gServiceName, gLayerId, gFieldName, true, whereClause, initFeatureCallback);
    }
}

function showLayer()
{
    switch(gServiceName)
    {
        case "Generic":
            showGenericLayer();
            break;
        case "Borough_Profile":
            showBoroughProfileLayer();
            break;
        case "UDP":
            showUDPLayer();
            break;
        default:
            alert("Service " + gServiceName + " is not configured");
    }

    if (gExtentPredefined)
        setExtent();
    else if (gFeatureName == "ALL")
        map.centerAndZoom(new esri.geometry.Point(523700, 179200, new esri.SpatialReference({wkid:27700})), 1);
    
    // This will be enabled in the query callback if an actual feature has been selected. 
    // This is only applicable in the map picker in Tridion, hence the check for null.
    var layerSelect = dojo.byId("layers");
    if (layerSelect != null)
        layerSelect.disabled = false;
    var featureSelect = dojo.byId("features");
    if (featureSelect != null)
        featureSelect.disabled = false;
}

function showSelectedLayers()
{
    var visibleLayers = new Array();
    var layerIds = gLayerId.split("-");
    for (var i = 0; i < layerIds.length; i++)
    {
        visibleLayers.push(layerIds[i]);
    }
    gFeatureServiceLayer.setVisibleLayers(visibleLayers);
}

function showGenericLayer()
{
    showSelectedLayers();
}

function showUDPLayer()
{
    // draw legend
    var html = "";
    var imageRoot = g_mapImagesRoot + "/UDP";

    var allLayers = "";
    var actualLayers = new Array();
    for (var n = 0; n < gUDPLegends.Layers.length; n++)
    {
        allLayers += gUDPLegends.Layers[n].Id;
        actualLayers.push(gUDPLegends.Layers[n].Id);
        if (n < gUDPLegends.Layers.length - 1)
            allLayers += "-";
    }
    html = getLegend(gUDPLegends, imageRoot, true, allLayers, "Legend", true);
    dojo.byId("legend").innerHTML = html;    

    // some of the grouping layers seem to cause problems, found layer 125 which is UDP 75K grouping corrupted things, so just set the actual layers visible
    gFeatureServiceLayer.setVisibleLayers(actualLayers);
    
}

function showBoroughProfileLayer()
{
    gFeatureServiceLayer.setOpacity(0.9);
    showSelectedLayers();
    if (gFeatureName == "ALL")
    {
        // draw legend
        var html = "";
        var imageRoot = g_mapImagesRoot + "/Borough_Profile";
        html = getLegend(gBoroughProfileLegends, imageRoot, false, gLayerId, null);

        // show/hide layers    
        if (gLayerName.indexOf("EDUCATION") == 0)
            html += "<br/>" + getLegend(gBoroughProfileLegends, imageRoot, true, "3-16", "Show/hide map layers", false); // libraries and open spaces
        else if (gLayerName.indexOf("ENVIRONMENT") == 0)
            html += "<br/>" + getLegend(gBoroughProfileLegends, imageRoot, true, "16", "Show/hide map layers", false); // libraries and open spaces
        else if (gLayerName.indexOf("HEALTH") == 0 && gLayerName.indexOf("HEALTH AND SOCIAL CARE - General information") == 0)
            html += "<br/>" + getLegend(gBoroughProfileLegends, imageRoot, true, "11-12-13", "Show/hide map layers", true); // libraries and open spaces
        else if (gLayerName.indexOf("HEALTH") == 0)
            html += "<br/>" + getLegend(gBoroughProfileLegends, imageRoot, true, "11-12-13", "Show/hide map layers", false); // libraries and open spaces
        else if (gLayerName.indexOf("TRANSPORT") == 0 && gLayerName.indexOf("TRANSPORT - Public transport - rail and underground stations") == -1)
            html += "<br/>" + getLegend(gBoroughProfileLegends, imageRoot, true, "4", "Show/hide map layers", false); // libraries and open spaces

        dojo.byId("legend").innerHTML = html;
    }
}

function legendRow(id, name, uri, lbl)
{
    this.layerId=id
    this.layerName=name
    this.symbolUri=uri
    this.label=lbl
}

function getLegend(legends, imageRoot, isToggleable, pLayerId, heading, isChecked)
{
    var html = "";
    var foundCount = 0;
    var legendRows = new Array();
    // iterate through all the layers in this mxd
    for (var i = 0; i < legends.Layers.length; i++)
    {
        var layerIds = pLayerId.split("-");
        // look for layer ids we want to put in the legend
        for (var j = 0; j < layerIds.length; j++)
        {
            var layer = legends.Layers[i];
            if (layer.Id == layerIds[j])
            {
                // process layer
                foundCount++;
                // check the layerName has not already been added to the legend
                var isAddedToLegend = false;
                var layerName = layer.Name.replace(/ /g, "_");
                for (var k = 0; k < legendRows.length; k++)
                {
                    if (layerName == legendRows[k].layerName)
                    {
                        isAddedToLegend = true;
                        legendRows[k].layerId += "-" + layer.Id;
                        //break;
                    }
                }
                if (!isAddedToLegend)
                {
                    if (heading == null || heading == "")
                    {
                        heading = layer.Legends[0].Heading;
                    }
                    var items = layer.Legends[0].Items;
                    // add all items in the layer to the legend
                    for (var k = 0; k < items.length; k++)
                    {
                        var lr = new legendRow(layer.Id, layerName, items[k].SymbolUri, items[k].Label);
                        legendRows.push(lr);
                    }
                }
                break;
            }
        }
        // once we found the layer/all the layers, exit the loop
        if (foundCount == layerIds.length)
            break;
    }
    for (var i = 0; i < legendRows.length; i++)
    {
        var addCheckbox = true;
        // if this layerIds are the same as the previous row, don't add a check box
        if (i > 0 && legendRows[i].layerId == legendRows[i-1].layerId)
            addCheckbox = false;
        html += getLegendRow(imageRoot, isToggleable, legendRows[i].layerId, legendRows[i].layerName, legendRows[i].symbolUri, legendRows[i].label, addCheckbox, isChecked);
    }
    // these lines are added backwards onto the beginning
    if (isToggleable && legendRows.length >= 5)
    {
        html = "<a href='#' onClick='hideAllLayers();'>Hide all layers</a></th>" + html;
        html = "<th><a href='#' onClick='showAllLayers(\"" + pLayerId + "\");'>Show all layers</a>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;" + html;
        html = "<th colspan='2' class='heading'>" + heading + "</th>" + html;        
    }
    else
        html = "<th colspan='3' class='heading'>" + heading + "</th>" + html;        
    html = "<table>" + html + "</table>";
    return html;
}

function getLegendRow(imageRoot, isToggleable, layerId, layerName, symbolUri, label, addCheckbox, isChecked)
{
    var html = "";
    var layerIds = layerId.toString().split("-");
    html += "<tr>";
    if (isToggleable)
    {
        html += "<td class='checkbox'>";
        if (addCheckbox)
        {
            html += "<input type='checkbox' class='checkbox' id='" + layerId + "' onClick='toggleLayer(\"" + layerId + "\");'";
            if (isChecked)
                html += " checked";
            html += "/>";
        }
        html += "</td>";
    }
    html += "<td class='symbol'><img src='" + imageRoot + "/" + layerIds[0] + "_" + layerName + "/" + symbolUri + "'></td>";
    html += "<td class='label'>";
    if (isToggleable)
    {
        html += "<a href='#' onClick='toggleLayer(\"" + layerId + "\"); return false;'>";
    }
    html += label;
    if (isToggleable)
        html += "</a></td>";
    html += "</tr>";
    return html;
}

function toggleLayer(layerIds)
{
    var visibleLayers = 0;
    for(var i = 0; i < map.layerIds.length; i++)
    {
        var layer = map.getLayer(map.layerIds[i])
        if (layer.visible)
            visibleLayers++;
    }
    gLayersLoaded = visibleLayers - 1;
    showLoading();
    // we'll only check for the first layerId, if we've found it in the visible layers, just turn them all off, if we can't find it, then turn them all on
    var visibleLayers = gFeatureServiceLayer.visibleLayers;
    var isHideLayers = false;
    var checkBox = dojo.byId(layerIds);

    var layerIds = layerIds.split("-");
    for (var i = 0; i < visibleLayers.length; i++)
    {
        if (visibleLayers[i] == layerIds[0])
        {   
            // layer is already in visible layers, need to hide
            isHideLayers = true;
            break;
        }
    }
    if (isHideLayers)
    {
        var newVisibleLayers = new Array();
        for (var i = 0; i < visibleLayers.length; i++)
        {
            var isHideLayer = false;
            for (var j = 0; j < layerIds.length; j++)
            {
                // push them all on except the ones we want to remove
                if (visibleLayers[i] == layerIds[j])
                {
                    isHideLayer = true;
                    break;
                }
            }
            if (!isHideLayer)
                newVisibleLayers.push(visibleLayers[i]);
        }
        gFeatureServiceLayer.setVisibleLayers(newVisibleLayers);
        checkBox.checked = false;
    }
    else
    {
        // not in there, push on
        gFeatureServiceLayer.setVisibleLayers(visibleLayers.concat(layerIds));
        checkBox.checked = true;
    }
}

function showAllLayers(layerIds)
{
    var visibleLayers = 0;
    for(var i = 0; i < map.layerIds.length; i++)
    {
        var layer = map.getLayer(map.layerIds[i])
        if (layer.visible)
            visibleLayers++;
    }
    gLayersLoaded = visibleLayers - 1;
    showLoading();
    var layerIds = layerIds.split("-")
    gFeatureServiceLayer.setVisibleLayers(layerIds);
    toggleCheckboxes(true);
}

function hideAllLayers()
{
    gLayersLoaded = 1;
    showLoading();
    gFeatureServiceLayer.setVisibleLayers(new Array());
    toggleCheckboxes(false);
}

function toggleCheckboxes(isChecked)
{
    var legend = dojo.byId("legend");
    var checkboxes = getElementsByClass("checkbox", legend);
    for (var i = 0; i < checkboxes.length; i++)
    {
        checkboxes[i].checked = isChecked;
    }
}

function initFeatureCallback(results)
{
    // TODO - what if more than one is returned
    var featureGeometry = results.features[0].geometry;

    switch(featureGeometry.type)
    {
        case "point":
            var symbol = new esri.symbol.PictureMarkerSymbol("/BasicMap/images/pinredshadow.png", 32, 32);
            symbol.setOffset(7, 14);
            var pt = new esri.geometry.Point(featureGeometry);
            gFeature = new esri.Graphic(pt, symbol);
            map.graphics.add(gFeature);  
            if (gExtentPredefined) 
                setExtent();
            else
                map.centerAndZoom(pt, 5);
            break;
        case "polygon":
            var outline = new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([0,0,0]), 1);
            var polySymbol = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, outline, new dojo.Color([255,0,1,0.25]));
            var polygon = new esri.geometry.Polygon(featureGeometry);
            if (gServiceName != "UDP")
            {
                gFeature = new esri.Graphic(polygon, polySymbol);
                map.graphics.add(gFeature);
            }
            if (gExtentPredefined) 
                setExtent();
            else
                map.setExtent(polygon.getExtent(), true);
            break;
        case "multipoint":
            var symbol = new esri.symbol.PictureMarkerSymbol("/BasicMap/images/pinredshadow.png", 32, 32);
            symbol.setOffset(7, 14);
            // THIS ONLY GRABS THE FIRST FEATURE IN A MULTIPOINT SET - apparently multipoint ones only ever have one in them in LBHF's implementation
            var pt = new esri.geometry.Point(featureGeometry.points[0]);
            gFeature = new esri.Graphic(pt, symbol);
            map.graphics.add(gFeature);  
            if (gExtentPredefined)
                setExtent()
            else
                map.centerAndZoom(pt, 5);
            break;
        case "polyline":
            var outline = new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([0,0,0]), 1);
            var polyline = new esri.geometry.Polyline(featureGeometry);
            if (gServiceName != "UDP")
            {
                gFeature = new esri.Graphic(polyline, outline);
                map.graphics.add(gFeature);  
            }
            if (gExtentPredefined)
                setExtent()
            else
                map.setExtent(polyline.getExtent(), true);
            break;
        default:
            alert(featureGeometry.type + " is not configured");
    }
    // This is only applicable in the map picker in Tridion, hence the check for null.
    var featureSelect = dojo.byId("features");
    if (featureSelect != null)
        featureSelect.disabled = false;
}
    
function clear(selectElement)
{
    while (selectElement.options.length > 0)
	    selectElement.remove(selectElement.options.length - 1);
}

function resizeMap()
{
    var mapdiv = dojo.byId("map");
    var sliderElement = dojo.byId("map_zoom_slider");
    var loadingImage = dojo.byId("loading");
    var dijitResets = getElementsByClass("dijitReset", sliderElement, "tr");
    mapdiv.style.width = gMapWidth;
    mapdiv.style.height = gMapHeight;
    loadingImage.style.top = (parseInt(gMapHeight.replace("px", ""))/2 - 16) + "px"; 
    map.resize();
    if (gDisplayZoomSlider)
    {
        dijitResets[1].style.display = "";
        dijitResets[2].style.display = "";
        dijitResets[3].style.display = "";
        sliderElement.style.height = "200px";
    }
    else
    {
        dijitResets[1].style.display = "none";
        dijitResets[2].style.display = "none";
        dijitResets[3].style.display = "none";
        sliderElement.style.height = "42px";
    }
}

// will attempt to set extent to global variables (in the case of showing on webpage), if set, otherwise (in the case of showing on map picker page), will return false
function setExtent()
{
    if (gExtentMinX == null || gExtentMinX == 0)
        return false;
    if (gExtentMinY == null || gExtentMinY == 0)
        return false;
    if (gExtentMaxX == null || gExtentMaxX == 0)
        return false;
    if (gExtentMaxY == null || gExtentMaxY == 0)
        return false;
        
    var extent = new esri.geometry.Extent(gExtentMinX, gExtentMinY, gExtentMaxX, gExtentMaxY, new esri.SpatialReference({wkid:27700}) );
    map.setExtent(extent);
    return true;
}





