function ExtMapTypeControl(opt_opts) {
    this.options = opt_opts || {}
};
ExtMapTypeControl.prototype = new GControl();
ExtMapTypeControl.prototype.initialize = function (map) {
    var me = this;
    var extDiv = document.createElement("div");
    if (me.options.useMapTypes) {
        var mapTypes = map.getMapTypes();
        var mapTypeDivs = me.addMapTypeButtons_(map);
        GEvent.addListener(map, "addmaptype", function () {
            var newMapTypes = map.getMapTypes();
            var newMapType = newMapTypes.pop();
            var newMapTypeDiv = me.createButton_(newMapType.getName());
            newMapTypeDiv.setAttribute('title', newMapType.getAlt());
            mapTypes.push(newMapType);
            mapTypeDivs.push(newMapTypeDiv);
            me.resetButtonEvents_(map, mapTypeDivs);
            extDiv.appendChild(newMapTypeDiv)
        });
        GEvent.addListener(map, "removemaptype", function () {
            for (var i = 0; i < mapTypeDivs.length; i++) {
                GEvent.clearListeners(mapTypeDivs[i], "click");
                extDiv.removeChild(mapTypeDivs[i])
            }
            mapTypeDivs = me.addMapTypeButtons_(map);
            me.resetButtonEvents_(map, mapTypeDivs);
            for (var i = 0; i < mapTypeDivs.length; i++) {
                extDiv.appendChild(mapTypeDivs[i])
            }
        });
        for (var i = 0; i < mapTypeDivs.length; i++) {
            me.toggleButton_(mapTypeDivs[i].firstChild, false);
            extDiv.appendChild(mapTypeDivs[i]);
            if (map.getCurrentMapType().getName() == mapTypeDivs[i].name) {
                me.toggleButton_(mapTypeDivs[i].firstChild, true)
            }
        }
        map.getContainer().appendChild(extDiv);
        var posX = 98;
        switch (mapTypes.length) {
        case 2:
            posX += 72;
            break;
        case 3:
            posX += 144;
            break;
        case 4:
            posX += 216;
            break
        }
    } else {
        var posX = me.options.posRight || 220
    }
    if (me.options.showSave) {
        map.addControl(new SavePosControl(), new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7, 31)))
    }
    if (me.options.showMore) {
        var layers = [{
            name: "Photos",
            obj: new GLayer("com.panoramio.all")
        },
        {
            name: "Videos",
            obj: new GLayer("com.youtube.all")
        },
        {
            name: "Wikipedia",
            obj: new GLayer("org.wikipedia.en")
        }];
        map.addControl(new MoreControl(layers, posX), new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(posX, 7)))
    }
    if (me.options.showTraffic) {
        if (me.options.showMore) posX += 94;
        map.addControl(new TrafficControl(me.options), new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(posX, 7)))
    }
    return extDiv
};
ExtMapTypeControl.prototype.addMapTypeButtons_ = function (map) {
    var me = this;
    var mapTypes = map.getMapTypes();
    var mapTypeDivs = [];
    for (var i = 0; i < mapTypes.length; i++) {
        mapTypeDivs[i] = me.createButton_(mapTypes[i].getName());
        mapTypeDivs[i].name = mapTypes[i].getName();
        mapTypeDivs[i].setAttribute('title', mapTypes[i].getAlt())
    }
    me.resetButtonEvents_(map, mapTypeDivs);
    return mapTypeDivs
};
ExtMapTypeControl.prototype.resetButtonEvents_ = function (map, mapTypeDivs) {
    var me = this;
    var mapTypes = map.getMapTypes();
    for (var i = 0; i < mapTypeDivs.length; i++) {
        var otherDivs = [];
        for (var j = 0; j < mapTypes.length; j++) {
            if (j != i) {
                otherDivs.push(mapTypeDivs[j])
            }
        }
        me.assignButtonEvent_(mapTypeDivs[i], map, mapTypes[i], otherDivs)
    }
    GEvent.addListener(map, "maptypechanged", function () {
        var divIndex = 0;
        var mapType = map.getCurrentMapType();
        for (var i = 0; i < mapTypes.length; i++) {
            if (mapTypes[i] == mapType) {
                divIndex = i
            }
        }
        GEvent.trigger(mapTypeDivs[divIndex], "click")
    })
};
ExtMapTypeControl.prototype.createButton_ = function (text) {
    var buttonDiv = document.createElement("div");
    this.setButtonStyle_(buttonDiv);
    buttonDiv.style.cssFloat = "left";
    buttonDiv.style.styleFloat = "left";
    var textDiv = document.createElement("div");
    textDiv.appendChild(document.createTextNode(text));
    textDiv.style.width = "6em";
    buttonDiv.appendChild(textDiv);
    return buttonDiv
};
ExtMapTypeControl.prototype.assignButtonEvent_ = function (div, map, mapType, otherDivs) {
    var me = this;
    GEvent.addDomListener(div, "click", function () {
        for (var i = 0; i < otherDivs.length; i++) {
            me.toggleButton_(otherDivs[i].firstChild, false)
        }
        me.toggleButton_(div.firstChild, true);
        map.setMapType(mapType)
    })
};
ExtMapTypeControl.prototype.toggleButton_ = function (div, boolCheck) {
    div.style.fontWeight = boolCheck ? "bold" : "normal";
    div.style.border = "1px solid #fff";
    var shadows = boolCheck ? ["Top", "Left"] : ["Bottom"];
    for (var j = 0; j < shadows.length; j++) {
        div.style["border" + shadows[j]] = "1px solid #b0b0b0"
    }
};
ExtMapTypeControl.prototype.getDefaultPosition = function () {
    return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7, 7))
};
ExtMapTypeControl.prototype.setButtonStyle_ = function (button) {
    button.style.color = "#000000";
    button.style.backgroundColor = "white";
    button.style.font = "small Arial";
    button.style.border = "1px solid black";
    button.style.padding = "0px";
    button.style.margin = "0px";
    button.style.textAlign = "center";
    button.style.fontSize = "12px";
    button.style.cursor = "pointer"
};

function TrafficControl(opt_opts) {
    this.options = opt_opts
};

function Inherit() {};
Inherit.prototype = ExtMapTypeControl.prototype;
TrafficControl.prototype = new Inherit();
TrafficControl.prototype.initialize = function (map) {
    var me = this;
    var trafficDiv = me.createButton_("Traffic");
    trafficDiv.setAttribute("title", "Show Traffic");
    trafficDiv.style.visibility = "hidden";
    trafficDiv.style.width = "6em";
    trafficDiv.firstChild.style.cssFloat = "left";
    trafficDiv.firstChild.style.styleFloat = "left";
    me.toggleButton_(trafficDiv.firstChild, false);
    var trafficInfo = new GTrafficOverlay({
        hide: true
    });
    trafficInfo.hidden = true;
    GEvent.addListener(trafficInfo, "changed", function (hasTrafficInView) {
        if (hasTrafficInView) {
            trafficDiv.style.visibility = "visible"
        } else {
            trafficDiv.style.visibility = "hidden"
        }
    });
    map.addOverlay(trafficInfo);
    GEvent.addDomListener(trafficDiv.firstChild, "click", function () {
        if (trafficInfo.hidden) {
            trafficInfo.hidden = false;
            trafficInfo.show()
        } else {
            trafficInfo.hidden = true;
            trafficInfo.hide()
        }
        me.toggleButton_(trafficDiv.firstChild, !trafficInfo.hidden)
    });
    if (me.options.showTrafficKey) {
        trafficDiv.style.width = "7.8em";
        var keyDiv = document.createElement("div");
        keyDiv.style.width = "1.3em";
        keyDiv.style.cssFloat = "left";
        keyDiv.style.styleFloat = "left";
        keyDiv.innerHTML = "?";
        var keyExpandedDiv = document.createElement("div");
        keyExpandedDiv.style.clear = "both";
        keyExpandedDiv.style.padding = "2px";
        var keyInfo = [{
            "color": "#30ac3e",
            "text": "&gt; 50 MPH"
        },
        {
            "color": "#ffcf00",
            "text": "25-50 MPH"
        },
        {
            "color": "#ff0000",
            "text": "&lt; 25 MPH"
        },
        {
            "color": "#c0c0c0",
            "text": "No data"
        }];
        for (var i = 0; i < keyInfo.length; i++) {
            keyExpandedDiv.innerHTML += "<div style='text-align: left'><span style='background-color: " + keyInfo[i].color + "'>&nbsp;&nbsp;</span>" + "<span style='color: " + keyInfo[i].color + "'> " + keyInfo[i].text + " </span>" + "</div>"
        }
        keyExpandedDiv.style.display = "none";
        GEvent.addDomListener(keyDiv, "click", function () {
            if (me.keyExpanded) {
                me.keyExpanded = false;
                keyExpandedDiv.style.display = "none"
            } else {
                me.keyExpanded = true;
                keyExpandedDiv.style.display = "block"
            }
            me.toggleButton_(keyDiv, me.keyExpanded)
        });
        me.toggleButton_(keyDiv, me.keyExpanded);
        trafficDiv.appendChild(keyDiv);
        trafficDiv.appendChild(keyExpandedDiv)
    }
    map.getContainer().appendChild(trafficDiv);
    return trafficDiv
};

function MoreControl(layers, posX) {
    MoreControl.prototype.layers = layers;
    MoreControl.prototype.posX = posX - 42;
    this.chosen = [];
    this.boxes = []
};
MoreControl.prototype = new Inherit();
MoreControl.prototype.initialize = function (map) {
    var me = this;
    me.moreDiv = me.createButton_("More...");
    me.moreDiv.setAttribute("title", "Show/Hide Layers");
    me.moreDiv.firstChild.style.width = "7em";
    me.toggleButton_(me.moreDiv.firstChild, false);
    me.map_ = map;
    me.createLayerBox_();
    GEvent.addDomListener(me.moreDiv, "mouseover", function () {
        if (window.timer) clearTimeout(timer);
        me.layerboxDiv.style.display = "block"
    });
    GEvent.addDomListener(me.moreDiv, "mouseout", function (e) {
        me.setClose(e)
    });
    GEvent.addDomListener(me.moreDiv, "click", function () {
        if (me.chosen.length > 0) {
            var copy = me.chosen.slice();
            for (var i = 0; i < copy.length; i++) {
                var index = parseInt(copy[i]);
                me.switchLayer(true, me.layers[index].obj);
                me.boxes[index].checked = true
            }
        } else {
            me.hideAll()
        }
    });
    map.getContainer().appendChild(me.moreDiv);
    return me.moreDiv
};
MoreControl.prototype.createLayerBox_ = function () {
    var me = this;
    me.layerboxDiv = document.createElement("div");
    me.layerboxDiv.style.textAlign = "left";
    me.layerboxDiv.style.font = "small Arial";
    me.layerboxDiv.style.fontSize = "12px";
    me.layerboxDiv.style.padding = "4px";
    me.layerboxDiv.style.width = "120px";
    me.layerboxDiv.style.backgroundColor = "#fff";
    me.layerboxDiv.style.border = "1px solid gray";
    me.layerboxDiv.style.cursor = "default";
    var input = [];
    for (var i = 0; i < me.layers.length; i++) {
        input[i] = me.createCheckbox_(i, me.layers[i].name);
        me.layerboxDiv.appendChild(input[i])
    }
    var ruler = document.createElement("hr");
    ruler.style.width = "92%";
    ruler.style.height = "1px";
    ruler.style.textAlign = "center";
    ruler.style.border = "1px";
    ruler.style.color = "#e2e2e2";
    ruler.style.backgroundColor = "#e2e2e2";
    var hidelink = document.createElement("a");
    hidelink.setAttribute("href", "javascript:void(0)");
    hidelink.style.color = "#a5a5a5";
    hidelink.style.textDecoration = "none";
    hidelink.style.cursor = "default";
    hidelink.style.marginLeft = "33px";
    var linktext = document.createTextNode("Hide all");
    hidelink.appendChild(linktext);
    me.layerboxDiv.appendChild(ruler);
    me.layerboxDiv.appendChild(hidelink);
    GEvent.addDomListener(hidelink, "click", function () {
        me.hideAll()
    });
    GEvent.addDomListener(me.layerboxDiv, "mouseout", function (e) {
        me.setClose(e)
    });
    var lpos = new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(me.posX, 25));
    lpos.apply(me.layerboxDiv);
    me.layerboxDiv.style.display = "none";
    me.map_.getContainer().appendChild(me.layerboxDiv);
    return me.layerboxDiv
};
MoreControl.prototype.createCheckbox_ = function (nr, name) {
    var me = this;
    var innerDiv = document.createElement("div");
    var checkbox = document.createElement("input");
    checkbox.setAttribute("type", "checkbox");
    var textSpan = document.createElement("span");
    textSpan.style.marginLeft = "2px";
    textSpan.appendChild(document.createTextNode(name));
    innerDiv.appendChild(checkbox);
    innerDiv.appendChild(textSpan);
    innerDiv.appendChild(document.createElement("br"));
    me.boxes.push(checkbox);
    GEvent.addDomListener(checkbox, "click", function () {
        me.switchLayer(this.checked, me.layers[nr].obj)
    });
    return innerDiv
};
MoreControl.prototype.setClose = function (e) {
    var me = this;
    if (!e) e = window.event;
    if (me.checkMouseLeave(me.layerboxDiv, e)) timer = window.setTimeout(function () {
        me.layerboxDiv.style.display = "none"
    }, 300)
};
MoreControl.prototype.checkMouseLeave = function (element, evt) {
    if (element.contains && evt.toElement) {
        return !element.contains(evt.toElement)
    } else if (evt.relatedTarget) {
        return !this.containsDOM(element, evt.relatedTarget)
    }
};
MoreControl.prototype.containsDOM = function (container, containee) {
    var isParent = false;
    do {
        if ((isParent = container == containee)) break;
        containee = containee.parentNode
    } while (containee != null);
    return isParent
};
MoreControl.prototype.switchLayer = function (checked, layer) {
    var me = this;
    var link = me.layerboxDiv.lastChild;
    var button = me.moreDiv.firstChild;
    if (checked) {
        me.map_.addOverlay(layer);
        me.chosen.length = 0;
        link.style.color = "#0000cd";
        link.style.textDecoration = "underline";
        link.style.cursor = "pointer";
        me.toggleButton_(button, true)
    } else {
        me.map_.removeOverlay(layer);
        if (!me.checkChecked()) {
            link.style.color = "#a5a5a5";
            link.style.textDecoration = "none";
            link.style.cursor = "default";
            me.toggleButton_(button, false)
        }
    }
};
MoreControl.prototype.hideAll = function () {
    var me = this;
    for (var i = 0; i < me.boxes.length; i++) {
        if (me.boxes[i].checked) {
            me.boxes[i].checked = false;
            me.switchLayer(false, me.layers[i].obj);
            me.chosen.push(i)
        }
    }
};
MoreControl.prototype.checkChecked = function () {
    var me = this;
    for (var i = 0; i < me.boxes.length; i++) {
        if (me.boxes[i].checked) return true
    }
    return false
};

function SavePosControl() {};
SavePosControl.prototype = new Inherit();
SavePosControl.prototype.initialize = function (map) {
    var me = this;
    var saved = [];
    var saveDiv = document.createElement("div");
    var saveButtonDiv = document.createElement("div");
    saveButtonDiv.setAttribute("title", "Save actual position and zoomlevel");
    me.setButtonStyle_(saveButtonDiv);
    saveButtonDiv.style.width = "7em";
    saveButtonDiv.style.padding = "1px";
    saveButtonDiv.style.marginBottom = "4px";
    saveButtonDiv.style.whiteSpace = "nowrap";
    saveButtonDiv.appendChild(document.createTextNode("Save Position"));
    saveDiv.appendChild(saveButtonDiv);
    var backButtonDiv = document.createElement("div");
    backButtonDiv.setAttribute("title", "Back to saved position");
    me.setButtonStyle_(backButtonDiv);
    backButtonDiv.style.width = "7em";
    backButtonDiv.style.padding = "1px";
    backButtonDiv.appendChild(document.createTextNode("To Saved"));
    saveDiv.appendChild(backButtonDiv);
    GEvent.addDomListener(saveButtonDiv, "click", function () {
        var center = map.getCenter();
        var zoom = map.getZoom();
        saved.splice(0, 2, center, zoom);
        alert("Saved Position: " + center.toUrlValue() + "\nZoomlevel: " + zoom)
    });
    GEvent.addDomListener(backButtonDiv, "click", function () {
        if (saved.length > 0) {
            map.setZoom(saved[1]);
            map.panTo(saved[0])
        }
    });
    map.getContainer().appendChild(saveDiv);
    return saveDiv
};