/*
 * Copyright © 2009 Jérémie Corbier <jeremie@famille-corbier.net>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

var Map = null;
var TrailLayer = null;
var Trips = {}
var CurTripID = null;

/* Map initialization and handling */
function initGeoportalMap()
{
    OpenLayers.Lang.setCode('fr');

    Map = new Geoportal.Viewer.Default(
        "Map",
        OpenLayers.Util.extend(
            { mode: 'normal' },
            gGEOPORTALRIGHTSMANAGEMENT
        )
    );

    if(Map)
    {
        Map.addGeoportalLayer(
            'GEOGRAPHICALGRIDSYSTEMS.MAPS:WMSC',
            { opacity: 1.0 }
        );

        Map.getMap().addControl(new OpenLayers.Control.ScaleLine());
        Map.getMap().addControl(new OpenLayers.Control.LoadingPanel());

        Map.setLayersPanelVisibility(false);
        Map.setInformationPanelVisibility(false);
        Map.openToolsPanel(true);

        resizeMap();

        /* Disable keyboard control */
        var kbControl = Map.getMap().getControlsByClass(
            OpenLayers.Control.KeyboardDefaults.prototype.CLASS_NAME)[0];
        if(kbControl)
        {
            kbControl.deactivate();
        }
    }
}

function setHikingTrailLayer(id)
{
    if(Map == null)
        return;

    if(TrailLayer)
    {
        Map.getMap().removeLayer(TrailLayer);
    }

    TrailLayer = Map.getMap().addLayer(
        "KML",
        "Parcours",
        Trips[id].trail,
        {
            visibility: true,
            minZoomLevel: 10,
            maxZoomLevel: 17
        },
        {}
    );

    Map.getMap().setCenterAtLonLat(
        Trips[id].center.latitude,
        Trips[id].center.longitude,
        13
    );
}

/* Trips loading from rando.xml */
function addHikingTrip(trip)
{
    var id = trip.getAttribute('id');
    var name = trip.getElement('name').get('text');
    var day = trip.getElement('date').get('text');
    var descfile = trip.getElement('description').get('text');
    var trail = trip.getElement('trail').get('text');
    var duration = trip.getElement('duration').get('text');

    var latitude = trip.getElement('latitude').get('text');
    var longitude = trip.getElement('longitude').get('text');

    Trips[id] =
    {
        'name': name,
        'day': day,
        'description': descfile,
        'trail': trail,
        'length': 0,
        'duration': duration,
        'center':
        {
            'latitude': latitude.toFloat(),
            'longitude': longitude.toFloat()
        }
    };

    if(CurTripID == null)
    {
        CurTripID = id;
    }
}

function loadTrips(text, xml)
{
    var trips = xml.getElements('rando');

    $each(
        trips,
        function(trip)
        {
            if(trip.nodeType == 1)
            {
                addHikingTrip(trip);
            }
        }
    );
}

function initTrips()
{
    var req = new Request({
        url: 'data/rando.xml',
        async: false,
        onSuccess: loadTrips
    }).get();
}

Number.prototype.toRad = function()
{
    return this * Math.PI / 180;
}

function distance(pos1, pos2)
{
    var r = 6371; /* km */
    var dlat = (pos2.latitude - pos1.latitude).toRad();
    var dlon = (pos2.longitude - pos1.longitude).toRad();

    var a = Math.sin(dlat/2) * Math.sin(dlat/2) +
            Math.cos(pos1.latitude.toRad()) * Math.cos(pos2.latitude.toRad()) *
            Math.sin(dlon/2) * Math.sin(dlon/2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

    return r * c * 1000; /* m */
}

function loadAltitudeData(id)
{
    /**
     * Get data.
     */
    var lines = null;

    var req = new Request({
        url: Trips[id].trail,
        async: false,
        onSuccess: function(text, xml)
        {
            var coords_str =
                xml.getElement('LineString').getElement('coordinates').get('text');
            lines = coords_str.match(/^.+$/mg);
        }
    }).get();

    if(!lines)
    {
        return;
    }

    var altitudes = [];
    var len = 0;
    var prev = null;

    $each(
        lines,
        function(line)
        {
            var coords = line.split(',');
            if(coords.length < 3)
                return;
            var cur =
            {
                'latitude': coords[0].toFloat(),
                'longitude': coords[1].toFloat()
            };

            if(prev)
            {
                len += distance(prev, cur);
            }
            prev = cur;

            altitudes.push([len, coords[2].toInt()]);
        }
    );

    /**
     * Draw the graph.
     */
    var f = Flotr.draw(
        $('Altitude'),
        [
            {
                data: altitudes,
                label: 'Altitude',
                lines: { fill: true } }
        ],
        { legend: { show: false }}
    );

    /*
     * Update trip length with GPS data
     */
    Trips[id].length = (len / 1000).round(3) + 'km';
}

function setActiveTrip(id)
{
    setHikingTrailLayer(id);
    loadAltitudeData(id);

    $('Title').set('html', '<h2>', Trips[id].name, '</h2>');
    $('Info').set(
        'html',
        '<ul><li> Date&nbsp;: ', Trips[id].day,
        '</li><li> Longueur&nbsp;: ', Trips[id].length,
        '</li><li> Temps&nbsp;: ', Trips[id].duration,
        '</li></ul>',
        '<div id="Description"></div>');

    var req = new Request.HTML({
        url: Trips[id].description,
        onSuccess: function(html)
        {
            $('Description').set('text', '');
            $('Description').adopt(html);
        }
    });
    req.send();

    $(CurTripID).removeClass('selected');
    $(id).addClass('selected');
    CurTripID = id;
}

/* UI initialization */
function initUI()
{
    /* Populate list of hiking trips */
    $each(
        Trips,
        function(trip, id)
        {
            var el = new Element(
                'li',
                {
                    'id': id,
                    'html': trip.name,
                    'events':
                    {
                        'click': function()
                        {
                            setActiveTrip(id);
                        }
                    }
                }
            );
            $('ListingContents').grab(el);
        }
    );

    /* Show first trip data */
    setActiveTrip(CurTripID);

    /* Resize map with browser window */
    window.addEvent(
        'resize',
        resizeMap
    );
}

function resizeMap()
{
    if(Map)
    {
        viewerSize = $('Viewer').getSize();

        Map.setSize(viewerSize.x, viewerSize.y);
    }
}

window.addEvent(
    'domready',
    function()
    {
        initTrips();
        initGeoportalMap();
        initUI();
    }
);
