/**
 *
 * This file stores the js functions for the tracks page
 * (except the ones regarding the map, the chart and the
 * statistics)
 *
 * @author     Vera Kern <vera@worksmartlabs.com>
 * @copyright  2008 WorkSmart Labs, Inc.
 */

// Names of the div containers used in tracks.tpl.php
var CHART_CONTAINER_NAME = 'trackChartContainer';
var CHART_BACKGROUND = 'chart_background';
var STATISTICS_CONTAINER_NAME = 'statisticsContainer';
var STATISTICS_BACKGROUND = 'statistics_background';
var SHARE_TRACK_CONTAINER_NAME = 'shareTrackContainer';
var MAP_CONTAINER_NAME = 'map';

// Menu when logged in normal
var SUB_MENU = new Array('delete_track',
                    'export_gpx',
                    'export_kml',
                    'share_track_dialog',
                    'tracks_arrow',
                    'separator',
                    'separator2',
                    'separator3'
                    );

// Menu when displaying a shared track
var SHARED_TRACK_SUB_MENU = new Array('export_gpx',
                                      'export_kml',
                                      'share_track_dialog',
                                      'separator2',
                                      'separator3',
                                      'tracks_arrow');

TracksPage.TracksPageType = { normal: 0, shared: 1, facebook: 2};

function TracksPage(mode, numTracks, trackId, radius, centerPointX, centerPointY, units) {
    this.numTracks_ = numTracks;
    if (this.numTracks_ == 0) {
        displayBlock(el('no_tracks_yet'));
        displayBlock(el('notracks_container'));
    } else {
        this.mode_ = mode;
        this.units_ = units;
        // At first the map is narrow
        this.mapIsWide_ = false;
        this.trackChart_ = new TrackChart(el(CHART_CONTAINER_NAME), el(CHART_BACKGROUND),
                                          this.mode_);
        this.trackStatistics_ = new TrackStatistics(el(STATISTICS_CONTAINER_NAME),
                                                    el(STATISTICS_BACKGROUND),
                                                    this.mode_, this.currentId_,
                                                    this.units_);
        this.shareTrackDialog_ = new ShareTrackDialog(el(SHARE_TRACK_CONTAINER_NAME));
        this.map_ = new Map(el(MAP_CONTAINER_NAME));
        if (this.mode_ != TracksPage.TracksPageType.facebook) {
            this.dashboard_ = new Dashboard();
        }

        this.currentTrack_ = null;
        this.lastTrack_ = null;
        this.runArray_ = null;
        this.elevationArray_ = null;

        // Set the events for the buttons on the trackspage.
        var toggleArrow = el('tracks_arrow');
        setClickHandler(toggleArrow, this, this.toggleWideNarrowTrackPanel);

        var exportGpxLink = el('export_gpx');
        setClickHandler(exportGpxLink, this,
                                    function() {
                                        this.exportTrack('gpx');
                                    }
                                );

        var exportKmlLink = el('export_kml');
        setClickHandler(exportKmlLink, this,
                                    function() {
                                        this.exportTrack('kml');
                                    }
                                );

        if (this.mode_ == TracksPage.TracksPageType.shared) {        	
        	this.currentId_ = trackId;
            this.currentTrack_ = 'track' + this.currentId_;
            this.clickOnTrack(this.currentId_);
        } else {
            this.radius_ = radius;
            this.centerX_ = centerPointX;
            this.centerY_ = centerPointY;
            if (this.mode_ == TracksPage.TracksPageType.normal) {
                var deleteTrack = el('delete_track');
                setClickHandler(deleteTrack, this, this.deleteTrack);
            }
            this.clickOnTotals(this.radius_, this.centerX_, this.centerY_);
        }
    }
}

/**
 * This function is called when a user clicks
 * on the first item in the tracklist (totals)
 * It draws the circle, hightlights the track
 * in the tracklist and hides the submenu.
 *
 * @param totalDistance float
 * @param centerPointX float
 * @param centerPointY float
 */
TracksPage.prototype.clickOnTotals = function() {
    this.currentId_ = null;
    this.map_.showMap();
    if (this.centerX_ != -1 && this.centerY_ != -1) {
        this.map_.drawTotalRunCircle(this.radius_, this.centerX_, this.centerY_);
    }
    this.trackHit('totals');
    this.trackChart_.hide();
    this.trackStatistics_.hide();
    el('footer').className = 'main footer';
    this.hideMenu();
    if (this.mode_ != TracksPage.TracksPageType.facebook) {
    	this.dashboard_.showDashboard();
    }
}

/**
 * This function is called when a user clicks
 * on a track in the tracklist.
 * It draws the run, hightlights the track in
 * the tracklist,shows the submenu and displays the
 * statistics.
 *
 * @param int trackId
 */
TracksPage.prototype.clickOnTrack = function(trackId) {
    this.currentId_ = trackId;
    this.parseTrackDataFromServer();
    interval = this.getCurrentInterval();
    this.trackHit('track' + this.currentId_);
    if (this.mode_ != TracksPage.TracksPageType.facebook) {
        this.dashboard_.hideDashboard();
    }
    this.showMenu();
    this.trackStatistics_.setCurrentId(this.currentId_);
    this.trackStatistics_.show(trackData[this.currentId_]);
    this.shareTrackDialog_.setValues(this.currentId_);
    if (interval == '') {
        this.emptyTrack();
    } else {
        this.map_.showMap();
        this.map_.drawRun(this.runArray_);
        if (this.elevationArray_.length > 1){
            this.trackChart_.showData(this.elevationArray_);
            el('footer').className = 'main footer bottom';
        } else {
            this.trackChart_.hide();
            el('footer').className = 'main footer middle';
        }
        el('footer').className = 'main footer bottom';
    }
}

// Called when the user clicks on a track in the tracklist
// Resets currentTrack and lastTrack and calls the highlighting function for
// the new track and removes the hightlighting styles from the last track
TracksPage.prototype.trackHit = function(trackName){
    this.lastTrack_ = this.currentTrack_;
    this.currentTrack_ = trackName;
    if (this.lastTrack_ != null) {
        el(this.lastTrack_).className = 'tracklist_item';
    }
    el(this.currentTrack_).className = 'tracklist_item highlighted';
}

// TODO(vera): Convert to using a separate attribute for the track
// instead of parsing (so currentTrackDiv.trackId).
TracksPage.prototype.exportTrack = function(type) {
    var signature = trackData[this.currentId_]['trackIdSignature'];
    window.location.href = 'exporter/export_' + type + '.php?trackId=' + this.currentId_ + 
                           '&signature=' + signature;
}

// Hides the submenu
TracksPage.prototype.hideMenu = function() {
    if (this.mode_ == TracksPage.TracksPageType.normal) {
        hideAll(SUB_MENU);
    } else {
        hideAll(SHARED_TRACK_SUB_MENU);
    }
}

// Shows the submenu
TracksPage.prototype.showMenu = function() {
    if (this.mode_ == TracksPage.TracksPageType.normal) {
        displayAll(SUB_MENU);
    } else {
        displayAll(SHARED_TRACK_SUB_MENU);
    }
}

/*
* Resizes the map and adjusts all needed sizes.
* Redraws the map to center the track.
*/
TracksPage.prototype.toggleWideNarrowTrackPanel = function() {
    if (this.mapIsWide_) {
        displayBlock(el('tracklist'));
        el('map').className = 'map';
        el('tracks_blue').className = 'tracks_blue';
        el('tracks_expand').className = 'tracks_expand';
        el('vertical_container').className = 'vertical_container';
        el('horizontal_container').className = 'horizontal_container';
        el('tracks_arrow').style.backgroundPosition = '-17px 0px';
        this.mapIsWide_ = false;
    }
    else {
        displayNone(el('tracklist'));
        el('map').className = 'map expanded';
        el('tracks_blue').className = 'tracks_blue expanded';
        el('tracks_expand').className = 'tracks_expand expanded';
        el('vertical_container').className = 'vertical_container expanded';
        el('horizontal_container').className = 'horizontal_container expanded';
        el('tracks_arrow').style.backgroundPosition = '0px 0px';
        this.mapIsWide_ = true;
    }
    this.map_.drawRun(this.runArray_);
}

TracksPage.prototype.emptyTrack = function() {
    this.map_.hideMap();    displayBlock(el('emtpyTrack_container'));
    // Show an empty chart if there is no data.
    // TODO(artem): Remove this code duplication with below once this logic is simplified.
    this.trackChart_.hide();
    el('footer').className = 'main footer middle';
}

// Called when the users clicks "delete"
TracksPage.prototype.deleteTrack = function() {
    // Asks the user to confirm the action
    var answer = confirm("Are you sure you want delete this track?");
    if (answer) {
        var ajaxRequest = createAjaxRequestObject();

        // Create the query to delete the current track and send it
        var queryString = "?trackId=" + this.getTrackIdFromDomNodeId_(this.currentTrack_) +
                          "&type=delete";
        ajaxRequest.open("GET", "update_track.php" + queryString, true);
        ajaxRequest.send(null);
        // Local variable that ensures the closure below will delete the
        // correct track (this in case the user clicks on another track
        // during the delete).
        var trackBeingDeleted = this.currentTrack_;

        var me = this;
        // When the state changes to "complete" (4)...
        ajaxRequest.onreadystatechange = function(){
            if(ajaxRequest.readyState == 4){
                // ...check whether the responseText equals 1
                // -> the responseText has the number of affected rows
                if (ajaxRequest.responseText == 1){
                    // Store the current Node
                    var node = el(trackBeingDeleted);
                    // Decrese the current number of tracks by one
                    me.numTracks_ -= 1;
                    // If there are no tracks left, unload the map and
                    // display some help for the user
                    if (me.numTracks_ == 0) {
                        // TODO(artem): Remove duplicated code.
                        me.map_.hideMap();
                        displayBlock(el('no_tracks_yet'));
                        displayBlock(el('notracks_container'));
                        displayNone(el('emtpyTrack_container'));
                        displayNone(el('delete'));
                    } else {
                        // If there are tracks left get the next node
                        // (or the previous in case it was the last node),
                        // hightlight it and get its trackdata
                        var trackToShow = me.getNextTrackIdToShow(node);
                        me.clickOnTrack(trackToShow);
                    }
                    // Remove the deleted track
                    node.parentNode.removeChild(node);
                } else if (ajaxRequest.responseText == 0){
                    // If the responseText is 0, track has already been deleted
                    alert ('Track was already deleted, please reload the page to refresh.');
                } else {
                    // No idea how to produce that since id is unique but just in case...
                    alert ('Could not delete track.' + ajaxRequest.responseText);
                }
            }
        }
    }
}

/**
 * Gets the track id from the dome node id (e.g. track123).
 * TODO(artem): Stop using DOM node ids for storage.
 *
 * @param trackDomNodeId The dome node id (e.g. track123).
 * @return
 */
TracksPage.prototype.getTrackIdFromDomNodeId_ = function(trackDomNodeId) {
    return trackDomNodeId.substring(5);
}

/**
 * This is a very hacky function that returns the next track in the list.
 * If this is the last item, it returns the previous track.
 *
 * TODO(artem): Switch away from this when we implement a whole JSON solution,
 * where the state is kept in the JSON data and not in the DOM.
 * @return
 */
TracksPage.prototype.getNextTrackIdToShow = function(currentTrackNode) {
    var trackDomId;
    // HACK: We have to go two steps, because there are text nodes in between.
    if (currentTrackNode.nextSibling.nextSibling.id) {
        trackDomId = currentTrackNode.nextSibling.nextSibling.id;
    } else {
        trackDomId = currentTrackNode.previousSibling.previousSibling.id;
    }
    return this.getTrackIdFromDomNodeId_(trackDomId);
}

TracksPage.prototype.setTextBack = function() {
    this.trackStatistics_.setTextBack();
}

/**
 * This function gets the to, from and message values for the email
 * and passes them as parameters to sendTrack.
 */
TracksPage.prototype.sendTrack = function() {
    var to = el('emailTo').value;
    var from = el('emailFrom').value;
    var msg = el('message').value;
    this.shareTrackDialog_.sendTrack(to, from, msg);
}

/**
 * This function returns the current interval depending
 * on the current id.
 */
TracksPage.prototype.getCurrentInterval = function() {
    return trackData[this.currentId_]['trackInterval'];
}

/**
 * This function parses the interval and passes the
 * runArray and the elevationArray to the runArray_
 * and elevationArray_ variables.
 */
TracksPage.prototype.parseTrackDataFromServer = function() {
    // Get the current interval and split it
    var interval = this.getCurrentInterval();
    var trackArray = interval.split("|");

    // TrackGArray contains an array for every part of the track
    // (if there was no break, it only contains one array)
    // Split every part of the track and create GLatLng with the coordinates
    var trackGArray = new Array();
    var trackElevationArray = new Array();
    for (var v = 0; v < trackArray.length; v++) {
        var runArray = trackArray[v].split(",");
        var runGArray = new Array();
        for (var m = 0; m < runArray.length; m+=3) {
            runGArray.push(new GLatLng (parseFloat(runArray[m]), parseFloat(runArray[m+1])));
            // For now, push all the data into a single array.
            // TODO(artem): This array currently has both the location hint (which does not
            // have an altitude) and the regular points. Remove this if once all of this
            // is in separate parameters.
            if (runArray[m+2]) {
                trackElevationArray.push(runArray[m+2]);
            }
        }
        trackGArray.push(runGArray);
    }
    this.elevationArray_ = trackElevationArray;
    this.runArray_ = trackGArray;
}