GribDataLoader = function (map) {
    this.sourceMap = map;
    this.urlsBase = "http://www.atposition.com/grib"; // Will be calculated later on
    this.needsRepainting = true;
    this.loadedMinx = 0;
    this.loadedMaxx = 0;
    this.loadedMiny = 0;
    this.loadedMaxy = 0;
    this.loadedZoom = 0;
    this.dropModifier = 2;
    this.dataView = null;
    this.loadedDate = 'current';
    this.arrowsMode = 'images';
    this.loadedWindXmlData = null;
    this.debuggerDiv = null;
    this.oldOverlayToBeRemoved = null;
    this.noneOptionSelectedLiteral = "Ninguna";
    this.closerDateOptionLiteral = "Fecha mas cercana";
    this.enableWindLiteral = "Ver mapa de viento";
    this.disableWindLiteral = "Quitar mapa de viento";
    this.dateSelector = null;
    this.enablerButton = null;
    this.dateInfoContainer = null;
    window.gribDataLoader = this;
    this.calculateURLSBase();
};

GribDataLoader.prototype.setLoadingMask = function (divElement) {
    this.loadingMask = divElement;
};

GribDataLoader.prototype.setDebuggerDiv = function (divElement) {
    this.debuggerDiv = divElement;
};

GribDataLoader.prototype.debug = function (message) {
    if (this.debuggerDiv) {
        this.debuggerDiv.innerHTML += "<br>" + message;
        this.debuggerDiv.scrollTop = this.debuggerDiv.scrollHeight;
    }
};

GribDataLoader.prototype.calculateURLSBase = function() {
    var allScripts = document.getElementsByTagName("script");
    for (var i = 0; i < allScripts.length; i++) {
        var scriptElement = allScripts[i];
        var scriptSource = scriptElement.getAttribute("src");
        if (scriptSource.indexOf("/gribWind.js") != -1 && scriptSource.indexOf("http://") == 0) {
            var hostName = scriptSource.substring(7, 7 + scriptSource.substring(7).indexOf("/"));
            this.urlsBase = "http://" + hostName + "/grib";
            break;
        }
    }
};


GribDataLoader.prototype.setEnablerButton = function (buttonElement) {
    this.enablerButton = buttonElement;
    if (this.isRunning()) {
        this.enablerButton.value = this.disableWindLiteral;
    } else {
        this.enablerButton.value = this.enableWindLiteral;
    }
    this.enablerButton.onclick = function() {
        window.gribDataLoader.toggleEnableOrDisable();
    }
}

GribDataLoader.prototype.setDateInfoContainer = function (containerElement) {
    this.dateInfoContainer = containerElement;
}

GribDataLoader.prototype.toggleEnableOrDisable = function () {
    if (this.isRunning()) {
        this.Stop();
    } else {
        this.Init();
    }
}

GribDataLoader.prototype.setDateSelector = function (selectElement) {
    this.dateSelector = selectElement;
    GDownloadUrl(this.urlsBase + "/data.kmz?op=listDates", function(data, responseCode) {
        selectElement.options.length = 0;
        var xml = GXml.parse(data);
        var markers = xml.documentElement.getElementsByTagName("date");
        selectElement.options[selectElement.options.length] = new Option(window.gribDataLoader.noneOptionSelectedLiteral, "");
        selectElement.options[selectElement.options.length] = new Option(window.gribDataLoader.closerDateOptionLiteral, "current");
        for (var i = 0; i < markers.length; i++) {
            var id = markers[i].getAttribute("id");
            var value = markers[i].getAttribute("value");
            selectElement.options[selectElement.options.length] = new Option(value, id);
        }
    });
    this.needsRepainting = true;
};

GribDataLoader.prototype.updateDateInfo = function (dateInfoContainer) {
    GDownloadUrl(this.urlsBase + "/data.kmz?op=getCurrentGribDate", function(data, responseCode) {
        var xml = GXml.parse(data);
        var dates = xml.documentElement.getElementsByTagName("currentDate");
        for (var i = 0; i < dates.length; i++) {
            dateInfoContainer.innerHTML = dates[i].getAttribute("value");
        }
    });
};

GribDataLoader.prototype.setArrowsMode = function (arrowsMode) {
    this.arrowsMode = arrowsMode;
    this.needsRepainting = true;
};

GribDataLoader.prototype.isViewObsolete = function () {
    if (this.sourceMap == null) return false;
    if (this.needsRepainting) {
        this.debug("View is marked as obsolete: needsRepainting=true");
        return true;
    }
    var mapBounds = this.sourceMap.getBounds();
    var minx = mapBounds.getSouthWest().lng();
    if (minx < this.loadedMinx) {
        this.debug("Map minx=" + minx + ", and loaded minx=" + this.loadedMinx + ". View is obsolete.");
        return true;
    }

    var maxx = mapBounds.getNorthEast().lng();
    if (maxx > this.loadedMaxx) {
        this.debug("Map maxx=" + maxx + ", and loaded maxx=" + this.loadedMaxx + ". View is obsolete.");
        return true;
    }

    var miny = mapBounds.getSouthWest().lat();
    if (miny < this.loadedMiny) {
        this.debug("Map miny=" + miny + ", and loaded miny=" + this.loadedMiny + ". View is obsolete.");
        return true;
    }

    var maxy = mapBounds.getNorthEast().lat();
    if (maxy > this.loadedMaxy) {
        this.debug("Map maxy=" + maxy + ", and loaded maxy=" + this.loadedMaxy + ". View is obsolete.");
        return true;
    }

    var currentZoom = this.sourceMap.getZoom();
    if (currentZoom != this.loadedZoom) {
        this.debug("Map zoom=" + currentZoom + ", and loaded zoom=" + this.loadedZoom + ". View is obsolete.");
        return true;
    }

    var timestamp = '';
    if (this.dateSelector && this.dateSelector.selectedIndex >= 0) {
        timestamp = this.dateSelector.options[this.dateSelector.selectedIndex].value;
        if (this.loadedDate && this.loadedDate != timestamp) {
            this.debug("Selected date=" + timestamp + ", Loaded date=" + this.loadedDate + ". View is obsolete.");
            return true;
        }

    }
    return false;
}

GribDataLoader.prototype.isViewVisible = function () {
    var timestamp = this.getTimestampToShow();
    return timestamp && timestamp != '';
}

GribDataLoader.prototype.getDrop = function () {
    var mapBounds = map.getBounds();
    var minx = mapBounds.getSouthWest().lng();
    var maxx = mapBounds.getNorthEast().lng();
    var dif = maxx - minx;
    var drop = 1;
    if (dif <= 10) {
        drop = 1;
    } else {
        drop = 1 + Math.round(dif / (18 * this.dropModifier));
    }
    if (drop > 10) drop = 10;
    if (drop < 1) drop = 1;
    return drop;
}

GribDataLoader.prototype.getTimestampToShow = function () {
    if (this.dateSelector) {
        var timestamp = '';
        if (this.dateSelector.selectedIndex >= 0) timestamp = this.dateSelector.options[this.dateSelector.selectedIndex].value;
        return timestamp;
    }
    else {
        return "current";
    }
}

GribDataLoader.prototype.periodicProcessing = function () {
    if (this.isViewVisible()) {
        this.debug("View is visible, that means there might be something to do.");
        if (this.isViewObsolete()) {
            this.needsRepainting = false;
            this.loadedDate = this.getTimestampToShow();
            this.loadedZoom = this.sourceMap.getZoom();
            this.debug("View is obsolete, reloading.");
            this.showLoadingMask();
            var mapBounds = map.getBounds();
            var minx = mapBounds.getSouthWest().lng();
            var maxx = mapBounds.getNorthEast().lng();
            var miny = mapBounds.getSouthWest().lat();
            var maxy = mapBounds.getNorthEast().lat();
            this.loadedMinx = Math.floor(minx / 10.0) * 10.0;
            this.loadedMaxx = Math.ceil(maxx / 10.0) * 10.0;
            this.loadedMiny = Math.floor(miny / 10.0) * 10.0;
            this.loadedMaxy = Math.ceil(maxy / 10.0) * 10.0;

            var kmlurl = this.urlsBase + "/data.kmz?op=wind&date=" + this.getTimestampToShow()
                    + "&minx=" + minx + "&maxx=" + maxx + "&miny=" + miny + "&maxy=" + maxy
                    + "&drop=" + this.getDrop()
                    + "&mode=" + this.arrowsMode;
            if (this.loadedWindXmlData) {
                if (this.oldOverlayToBeRemoved) {
                    this.sourceMap.removeOverlay(this.oldOverlayToBeRemoved);
                }
                this.oldOverlayToBeRemoved = this.loadedWindXmlData;
            }
            this.loadedWindXmlData = new GGeoXml(kmlurl);
            this.sourceMap.addOverlay(this.loadedWindXmlData);
            GEvent.addListener(this.loadedWindXmlData, 'load', function() {
                if (window.gribDataLoader.loadedWindXmlData.loadedCorrectly()) {
                    if (window.gribDataLoader.oldOverlayToBeRemoved)
                        window.gribDataLoader.sourceMap.removeOverlay(window.gribDataLoader.oldOverlayToBeRemoved);
                    window.gribDataLoader.hideLoadingMask();
                } else {
                    window.gribDataLoader.debug(kmlurl + " Failed to load correctly. Marking as dirty.");
                    window.gribDataLoader.needsRepainting = true;
                }
            });

            if (this.dateInfoContainer) {
                this.updateDateInfo(this.dateInfoContainer);
            }
        }
    } else {
        this.debug("View is not visible, removing existing layer if any.");
        if (this.loadedWindXmlData) {
            this.sourceMap.removeOverlay(this.loadedWindXmlData);
            this.loadedWindXmlData = null;
        }
    }
    this.timer = setTimeout('if(window.gribDataLoader) window.gribDataLoader.periodicProcessing()', 5000);
};

GribDataLoader.prototype.Init = function () {
    this.needsRepainting = true;
    this.timer = setTimeout('if(window.gribDataLoader) window.gribDataLoader.periodicProcessing()', 100);
    if (this.enablerButton) this.enablerButton.value = this.disableWindLiteral;
};

GribDataLoader.prototype.Stop = function () {
    if (this.timer) clearTimeout(this.timer);
    if (this.loadedWindXmlData) {
        this.sourceMap.removeOverlay(this.loadedWindXmlData);
        this.loadedWindXmlData = null;
    }
    this.timer = null;
    if (this.enablerButton) this.enablerButton.value = this.enableWindLiteral;
};

GribDataLoader.prototype.isRunning = function () {
    return this.timer != null;
};

GribDataLoader.prototype.showLoadingMask = function () {
    if (this.loadingMask) this.loadingMask.style.display = 'block';
};

GribDataLoader.prototype.hideLoadingMask = function () {
    if (this.loadingMask) this.loadingMask.style.display = 'none';
};
