﻿/**
* Forecast ruler control constructor.
*
* @class The forecast ruler control with a draggable handler.
*
* @augments HControl
* @constructor
*/
function HForecastRulerControl() {
    var div = document.createElement("div");
    div.id = "HForecastRulerControl";

    HMapHelpers.applyStyle([div], {
        position: "absolute",
        fontFamily: "Verdana, Arial",
        fontSize: "12px",
        fontWeight: "normal",
        zIndex: HControl.Z_INDEX
    });

    // Auto scroll weather button
    var autoScrollButton = document.createElement("img");
    autoScrollButton.id = "HautoScrollButton";
    autoScrollButton.src = HForecastRulerControl.GFX_URL + "play_weather.png";
    HMapHelpers.applyStyle([autoScrollButton], {
        position: "absolute",
        cursor: "pointer",
        width: "29px",
        height: "28px",
        left: "275px",
        top: "3px"
    });

    // Previous hour button
    var prevHourButton = document.createElement("img");
    prevHourButton.id = "HprevHourButton";
    prevHourButton.src = HForecastRulerControl.GFX_URL + "weatherruler_prevhour.png";
    HMapHelpers.applyStyle([prevHourButton], {
        position: "absolute",
        cursor: "pointer",
        width: "15px",
        height: "16px",
        left: "304px",
        top: "13px"
    });

    // Next hour button
    var nextHourButton = document.createElement("img");
    nextHourButton.id = "HnextHourButton";
    nextHourButton.src = HForecastRulerControl.GFX_URL + "weatherruler_nexthour.png";
    HMapHelpers.applyStyle([nextHourButton], {
        position: "absolute",
        cursor: "pointer",
        width: "15px",
        height: "16px",
        left: "319px",
        top: "13px"
    });

    // container for hour click icons
    var hourClicks = document.createElement("div");
    HMapHelpers.applyStyle([hourClicks], {
        position: "absolute"
    });

    // background frame
    var bkgImg = document.createElement("img");
    bkgImg.id = "HweatherRulerBackground"
    bkgImg.src = HForecastRulerControl.GFX_URL + "weatherruler_bg.jpg";
    HMapHelpers.applyStyle([bkgImg], {
        position: "absolute",
        cursor: "auto"
    });
    hourClicks.appendChild(bkgImg);

    var curDate = Date.today.addHours(new Date().getHours());
    var curHour = curDate.getHours();

    curDate = Date.today.addHours(new Date().getHours());

    var j = 0;

    for (var i = 0; i < HForecastRulerControl.NUMBER_OF_HOURS; i++) {
        HForecastRulerControl.TIMES[i] = curDate.addHours(i);

        var hour = HForecastRulerControl.TIMES[i].getHours();

        if (hour == 9 || hour == 15 || hour == 21) {
            HForecastRulerControl.TIMESWITHDATA[j++] = HForecastRulerControl.TIMES[i];
        }
    }

    HForecastRulerControl.HOUR_CLICK_CONTAINER_WIDTH = HForecastRulerControl.HOUR_CLICK_OFFSET + HForecastRulerControl.TIMES.length * HForecastRulerControl.HOUR_CLICK_WIDTH;

    this.hourIcons = [];
    for (var i = 0; i < HForecastRulerControl.TIMES.length; i++) {
        this.hourIcons[i] = document.createElement("div");

        this.hourIcons[i].id = "HhourIcon" + i;

        if (i % 3 == 0) {
            var h = HForecastRulerControl.TIMES[i].getHours();
            //this.hourIcons[i].innerHTML = (h < 10 ? "0" : "") + h;
            this.hourIcons[i].innerHTML = (h < 10 ? "0" : "") + h;
        }

        HMapHelpers.applyStyle([this.hourIcons[i]], {
            position: "absolute",
            fontSize: "8px",
            color: "#000",
            cursor: "pointer",
            zIndex: HControl.Z_INDEX,
            textAlign: "center",
            width: "6px",
            height: "24px",
            left: (HForecastRulerControl.HOUR_CLICK_OFFSET + HForecastRulerControl.HOUR_CLICK_WIDTH * (i) - 2) + "px",
            top: "5px"
        });

        // This is just to make hour icons clickable in Internet Explorer.
        var clickLayer = document.createElement("div");
        HMapHelpers.applyStyle([clickLayer], {
            position: "absolute",
            top: "0",
            left: "0",
            width: "6px",
            height: "24px",
            backgroundColor: "white",
            filter: "alpha(opacity=0)",
            opacity: 0
        });

        this.hourIcons[i].appendChild(clickLayer);

        hourClicks.appendChild(this.hourIcons[i]);
    }


    // draggable forecast handle container
    var forecastHandle = document.createElement("div");
    HMapHelpers.applyStyle([forecastHandle], {
        position: "absolute",
        left: "9px",
        top: "16px",
        zIndex: (HControl.Z_INDEX + 1),
        cursor: "e-resize"
    });

    // image of forecast handle
    var forecastHandleImg = document.createElement("img");
    forecastHandleImg.src = HForecastRulerControl.GFX_URL + "weatherruler_marker.gif";
    forecastHandle.appendChild(forecastHandleImg);

    hourClicks.appendChild(forecastHandle);

    div.appendChild(hourClicks);
    div.appendChild(autoScrollButton);

    div.appendChild(prevHourButton);
    div.appendChild(nextHourButton);

    this.forecastHandle = forecastHandle;
    this.element = div;
}

// HForecastRulerControl inherits from HControl
HForecastRulerControl.prototype = new HControl();

HForecastRulerControl.GFX_URL = "http://www.hitta.se/Images/hmap/";          // URL prefix
HForecastRulerControl.NUMBER_OF_HOURS = 37;
HForecastRulerControl.TIMES = [];
HForecastRulerControl.TIMESWITHDATA = [];
HForecastRulerControl.WIDTH = 335;               // width of forecastruler control (to calculate position)
HForecastRulerControl.HOUR_CLICK_OFFSET = 9;     // horizontal offset for hour click numbers
HForecastRulerControl.HOUR_CLICK_WIDTH = 7;     // spacing between hour click numbers
HForecastRulerControl.FORECAST_HANDLE_WIDTH = 7;    // width of forecast handle image
HForecastRulerControl.HOUR_CLICK_CONTAINER_WIDTH = HForecastRulerControl.HOUR_CLICK_OFFSET + HForecastRulerControl.TIMES.length * HForecastRulerControl.HOUR_CLICK_WIDTH;
HForecastRulerControl.ANIM_INTERVAL = 10;        // timer interval for forecast handle animation
HForecastRulerControl.ANIM_SPEED = 5;            // lower = faster
HForecastRulerControl.AUTOSCROLL_SPEED = 80;      // lower = faster

HForecastRulerControl.prototype.selectedDate = null;
HForecastRulerControl.prototype.timer = null;

/**
* Acts as a proxy function during the time we do not have complete access to data from Storm
* 
* @param {time} time The raw time as provided by user
* @param {triggerEvent} triggerEvent Weather or not to trigger event upon time select
*/
HForecastRulerControl.prototype.selectForecast = function(time, triggerEvent) {
    // TODO: find nearest point in time where data is present.
    /*
    var me = this;

    var validHours = [9, 15, 21];

    var smallestDiff = 1000;
    var hour;

    for (var i = 0; i < validHours.length; i++) {

        var diff = Math.abs(time.getHours() - validHours[i]);
    if (diff < smallestDiff) {
    smallestDiff = diff;
    hour = validHours[i];
    }
    }

    console.log(hour, triggerEvent);

    time.setHours(hour);
    */

    var me = this;
    me.selectedDate = time;

    if (me.timer != null)
        clearTimeout(me.timer);

    // use timeout so that we don't have to make an AJAX call for each hour on fast handle drags.
    me.timer = setTimeout(function() {
        //console.log(me.selectedDate, HForecastRulerControl.TIMESWITHDATA, triggerEvent);
        WeatherToolbar.selectForecast(me.selectedDate, HForecastRulerControl.TIMESWITHDATA, triggerEvent)
        WeatherToolbar.showSimpleTime(me.selectedDate);
    }, 100);
};




/**
* Initiate forecast ruler control.
*
* @param {HMap} hmap The HMap instance.
* @param {HControlPosition} position Position of control.
* @private
*/
HForecastRulerControl.prototype.init = function(hmap, position) {
    var me = this;

    // call overridden init in "super class"
    HControl.prototype.init.apply(me, [hmap, position]);

    var prevHourButton = document.getElementById("HprevHourButton");
    var nextHourButton = document.getElementById("HnextHourButton");
    var autoScrollButton = document.getElementById("HautoScrollButton");

    HEvent.addDomListener(autoScrollButton, "click", function(e) {
        me.autoScroll(300);
        HEvent.stopEvent(e);
    });
    HEvent.addDomListener(prevHourButton, "click", function(e) {
        me.shiftHour(-1);
        HEvent.stopEvent(e);
    });
    HEvent.addDomListener(nextHourButton, "click", function(e) {
        me.shiftHour(1);
        HEvent.stopEvent(e);
    });


    // stop click on forecast ruler background
    var forecastRulerBkg = document.getElementById("HweatherRulerBackground");
    HEvent.addDomListener(forecastRulerBkg, "click", HEvent.stopEvent);
    HEvent.addDomListener(forecastRulerBkg, "dblclick", HEvent.stopEvent);

    // stop double click events on hour-shift buttons
    HEvent.addDomListener(prevHourButton, "dblclick", HEvent.stopEvent);
    HEvent.addDomListener(nextHourButton, "dblclick", HEvent.stopEvent);

    // click on hour clicks
    for (var i = 0; i < HForecastRulerControl.TIMES.length; i++) (function(i) {

        HEvent.addDomListener(me.hourIcons[i], "click", function(e) {
            var time = HForecastRulerControl.TIMES[i];
            //WeatherToolbar.selectForecast(time.toString());
            me.selectForecast(time);
            me.isDragging = false;
            HEvent.stopEvent(e);
        });
    })(i);

    // forecast handle event listeners
    HEvent.addDomListener(this.forecastHandle, "mousedown", function(e) { me.startForecastHandleDrag(e); });
    HEvent.addDomListener(document, "mouseup", function(e) { me.stopForecastHandleDrag(e); });
    HEvent.addDomListener(document, "mousemove", function(e) { me.forecastHandleDrag(e); });

    this.isDragging = false;

    var thisHour = Date.today.addHours(new Date().getHours());
    //this.updateHourClick(thisHour, true);
    Forecast.date = thisHour;

    // listen to forecast hour changes  
    HEvent.addListener(WeatherToolbar, WeatherToolbar.EVENT_FORECASTDATE_SELECT, function(time) { me.updateHourClick(time); });
    //HEvent.addListener(me.hmap, HMap.EVENT_INTERNAL_MAP_TYPE_CHANGED, function() { me.updateStatus(null); });
    //HEvent.addListener(HStandardMapProvider, HMap.EVENT_INTERNAL_MAP_STATUS_UPDATE, function(statusObj) { me.updateStatus(statusObj); });

    this.selectForecast(thisHour);
};

HForecastRulerControl.prototype.updateHourClick = function(newDate, skipAnim) {

    var timeIndex = -1;

    for (var i = 0; i < HForecastRulerControl.TIMES.length; i++) {
        if (newDate.toString() == HForecastRulerControl.TIMES[i].toString()) {
            timeIndex = i;
            break;
        }
    }

    var me = this;

    var current = me.forecastHandle.offsetLeft;
    var dest = HForecastRulerControl.HOUR_CLICK_OFFSET + (HForecastRulerControl.HOUR_CLICK_WIDTH * (timeIndex));

    if (arguments[1] || false) {
        // skip animation
        me.forecastHandle.style.left = dest + "px";
    } else {
        // animate movement
        var timer = setInterval(function() {
            var step = (dest - current) / HForecastRulerControl.ANIM_SPEED;
            step = (step < 0) ? Math.floor(step) : Math.ceil(step);

            current += step;
            me.forecastHandle.style.left = current + "px";

            if (current == dest) {
                clearInterval(timer);
            }
        }, HForecastRulerControl.ANIM_INTERVAL);
    }

    
};


/**
* Update zoom level status of zoom control. Call with JSON status object or
* when map type is changed.
*
* @param {Object} statusObj JSON zoom level status object. If null update
*                           will use previous status object but check current
*                           map type.
* @private
*/
/*
HForecastRulerControl.prototype.updateStatus = function(statusObj) {

//console.log("updateStatus");

if (statusObj != null) {
// save status
this.currentStatus = statusObj;
}

// update available zoom levels
if (this.currentStatus) {
var mapType = this.hmap.getMapType();

for (var i = 1; i <= HForecastRulerControl.HOURS; i++) {
if (i >= this.currentStatus[mapType].min &&g22
i <= this.currentStatus[mapType].max) {
// zoom level available
HMapHelpers.applyStyle([this.hourIcons[i]], {
backgroundColor: "#fff"
});
} else {
// zoom level not available
HMapHelpers.applyStyle([this.hourIcons[i]], {
backgroundColor: "#C0C0C0"
});
}
}
}
};
*/

/**
* Event listener to start drag of forecast handle.
*
* @param {Event} e Mouse event.
* @private
*/
HForecastRulerControl.prototype.startForecastHandleDrag = function(e) {

    var pos = HMapHelpers.getMousePosition(e);
    HEvent.stopEvent(e);
    this.dragStartX = pos.x;
    this.dragHandleStartX = this.forecastHandle.offsetLeft;
    this.isDragging = true;
};

/**
* Event listener to stop drag of forecast handle.
*
* @param {Event} e Mouse event.
* @private
*/
HForecastRulerControl.prototype.stopForecastHandleDrag = function(e) {

    var me = this;

    if (this.isDragging) {
        var pos = HMapHelpers.getMousePosition(e);
        var left = this.restrictForecastHandleBounds(this.dragHandleStartX + (pos.x - this.dragStartX));

        // calculate hour click where handle is dropped on
        var time = HForecastRulerControl.TIMES[Math.round((left - HForecastRulerControl.HOUR_CLICK_OFFSET) / HForecastRulerControl.HOUR_CLICK_WIDTH)];

        //WeatherToolbar.selectForecast(time.toString());
        //HForecastRulerControl.selectForecast(time);
        me.selectForecast(time);

        this.isDragging = false;
    }
};

/**
* Event listener to manage mouse movement when dragging the forecast handle.
*
* @param {Event} e Mouse event.
* @private
*/
HForecastRulerControl.prototype.forecastHandleDrag = function(e) {

    if (this.isDragging) {

        var me = this;
        var pos = HMapHelpers.getMousePosition(e);
        var left = this.restrictForecastHandleBounds(this.dragHandleStartX + (pos.x - this.dragStartX));
        var time = HForecastRulerControl.TIMES[Math.round((left - HForecastRulerControl.HOUR_CLICK_OFFSET) / HForecastRulerControl.HOUR_CLICK_WIDTH)];

        //if (Forecast.date.toString() != time.toString()) {
        if (me.selectedDate != time.toString()) {
            //WeatherToolbar.selectForecast(time.toString(), false);
            //HForecastRulerControl.selectForecast(time, false);
            me.selectForecast(time, false);
            WeatherToolbar.showSimpleTime(me.selectedDate);
        }

        this.forecastHandle.style.left = left + "px";

        HEvent.stopEvent(e);
    }
};


HForecastRulerControl.prototype.autoScroll = function(rate) {

    var me = this;
    var current = me.forecastHandle.offsetLeft;
    var dest = HForecastRulerControl.HOUR_CLICK_OFFSET + (HForecastRulerControl.HOUR_CLICK_WIDTH * (HForecastRulerControl.TIMES.length - 1));

    if (current != dest) {

        var timer = setInterval(function() {

            step = 1;
            current += step;
            me.forecastHandle.style.left = current + "px";

            var time = HForecastRulerControl.TIMES[Math.round((current - HForecastRulerControl.HOUR_CLICK_OFFSET) / HForecastRulerControl.HOUR_CLICK_WIDTH)];

            if (me.selectedDate != time.toString()) {
                //WeatherToolbar.selectForecast(time.toString(), false);
                //HForecastRulerControl.selectForecast(time, false);
                me.selectForecast(time, false);
                WeatherToolbar.showSimpleTime(me.selectedDate);
            }

            if (current == dest) {
                clearInterval(timer);
            }
        }, HForecastRulerControl.AUTOSCROLL_SPEED);
    }
};


HForecastRulerControl.prototype.shiftHour = function(change) {

    var me = this;

    if (Forecast.date.addHours(change) >= HForecastRulerControl.TIMES[0] && Forecast.date.addHours(change) <= HForecastRulerControl.TIMES[HForecastRulerControl.TIMES.length - 1]) {
        //WeatherToolbar.selectForecast(Forecast.date.addHours(change).toString());
        //HForecastRulerControl.selectForecast(Forecast.date.addHours(change));
        //me.selectForecast(Forecast.date.addHours(change));
        //me.selectForecast(Forecast.date.addHours(change));
        me.selectForecast(me.selectedDate.addHours(change));
    }

};


/**
* Restrict horizontal pixel coordinates of forecast handle position to make sure it is
* within the bounds of the forecast ruler control.
*
* @param {Number} left Left coordinate in pixels.
* @returns {Number} Left coordinate capped.
* @private
*/
HForecastRulerControl.prototype.restrictForecastHandleBounds = function(left) {

    // check left bound
    if (left < HForecastRulerControl.HOUR_CLICK_OFFSET) {
        left = HForecastRulerControl.HOUR_CLICK_OFFSET;
    }

    // check right bound
    if (left >= HForecastRulerControl.HOUR_CLICK_CONTAINER_WIDTH - HForecastRulerControl.FORECAST_HANDLE_WIDTH) {
        left = HForecastRulerControl.HOUR_CLICK_CONTAINER_WIDTH - HForecastRulerControl.FORECAST_HANDLE_WIDTH;
    }

    return left;
}

/**
* Get default position of foreacst control.
*
* @returns {HControlPosition} Control position object.
*/
HForecastRulerControl.prototype.getDefaultPosition = function() {

    return new HControlPosition(HControlPosition.ANCHOR_BOTTOM_CENTER, new HPoint(-Math.round(HForecastRulerControl.WIDTH / 2), -37));

};

