/*
In this example, we will draw flight paths on a world map. We'll use the Image
module and some of the built-in Ox.js functions for dealing with geographic
coordinates.
*/
'use strict';

/*
Include the image module.
*/
Ox.load('Image', function() {

    /*
    This creates an image object from the specified source.
    */
    Ox.Image('jpg/earth720.jpg', function(image) {

            /*
            We want to map the route New York - London - Tokyo - Johannesburg -
            Sydney - Sao Paulo - New York.
            */
        var airports = [
                {name: 'JFK', lat: 40.643841, lng: -73.782304},
                {name: 'LHR', lat: 51.480902, lng: -0.464773},
                {name: 'NRT', lat: 35.553457, lng: 139.76532},
                {name: 'JNB', lat: -26.140009, lng: 28.242781},
                {name: 'SYD', lat: -33.93567, lng: 151.164322},
                {name: 'GRU', lat: -23.62754, lng: -46.700821},
            ],
            /*
            To get the width (and height) of the image, we call its
            <code>getSize</code> method.
            */
            mapSize = image.getSize().width,
            /*
            Ox.getLine returns a line from one lat/lng pair to another, as an
            array of <code>Math.pow(2, precision) + 1</code> points.
            */
            precision = 8,
            paths = airports.map(function(airport, i) {
                return Ox.getLine(
                    airport,
                    /*
                    We make sure the last airport gets connected with the first
                    one.
                    */
                    airports[(i + 1) % airports.length],
                    precision
                );
            });

        /*
        Ox.getXYByLatLng takes a lat/lng pair and returns its x/y position on a
        1×1 Mercator position, <code>{x: 0, y: 0}</code> being the bottom left,
        <code>{x: 1, y: 1}</code> being the top right.
        */
        function getXY(point) {
            var xy = Ox.getXYByLatLng(point);
            return [xy.x * mapSize, xy.y * mapSize];
        }

        /*
        For each path, we have to check if it crosses the edge of the map that
        runs through the Pacific. Note that our test (a line crosses the edge
        if it spans more than 180 degrees longitude) is obviously incorrect,
        but works in our case, since all lines are sufficiently short.
        */
        paths.forEach(function(path) {
            var parts = [path];
            Ox.loop(path.length - 1, function(i) {
                var lat, lng;
                if (Math.abs(path[i].lng - path[i + 1].lng) > 180) {
                    /*
                    We split the path in two parts.
                    */
                    parts = [path.slice(0, i + 1), path.slice(i + 1)];
                    /*
                    We get the lat/lng of the points where the line leaves
                    and enters the map...
                    */
                    lat = Ox.getCenter(path[i], path[i + 1]).lat;
                    lng = path[i].lng < 0 ? [-180, 180] : [180, -180];
                    /*
                    ... and append them to the end of the first part and the
                    beginning of the second part.
                    */
                    parts[0].push({lat: lat, lng: lng[0]});
                    parts[1].unshift({lat: lat, lng: lng[1]});
                    /*
                    Ox.Break() breaks the loop. Again, note that this assumes no
                    path will cross the edge more than once.
                    */
                    Ox.Break();
                }
            });
            /*
            We draw each part.
            */
            parts.forEach(function(part) {
                image.drawPath(part.map(getXY), {color: 'white'});
            });
        });

        /*
        Now lets add some markers.
        */
        airports.forEach(function(airport, i) {
                /*
                <code>j</code> is the index of the next airport.
                */
            var j = (i + 1) % airports.length,
                /*
                These are the options for the draw functions of the image. Some
                of the properties only apply to <code>drawPath</code>, some
                only to <code>drawText</code>, but we can pass all of them to
                both.
                */
                options = {
                    close: true,
                    color: 'rgba(255, 255, 255, 0.75)',
                    fill: 'rgba(0, 0, 0, 0.5)',
                    font: 'bold 11px Lucida Grande, sans-serif',
                    textAlign: 'center'
                },
                /*
                Ox.getDistance returns the distance, in meters, between two
                lat/lng pairs, and Ox.formatNumber adds thousands separators.
                */
                text = airports[i].name + '-' + airports[j].name + ' '
                    + Ox.formatNumber(Math.round(
                        Ox.getDistance(airports[i], airports[j]) / 1000
                    )) + ' km',
                /*
                Ox.getCenter returns the midpoint between two lat/lng pairs.
                In our case, this is where we want to attach markers.
                */
                xy = getXY(Ox.getCenter(airports[i], airports[j])),
                x = Math.round(xy[0]),
                y = Math.round(xy[1]);
            /*
            This is the marker...
            */
            image.drawPath([
                [x, y],
                [x + 4, y - 16],
                [x + 64, y - 16],
                [x + 64, y - 32],
                [x - 64, y - 32],
                [x - 64, y - 16],
                [x - 4, y - 16]
            ], options);
            /*
            ... and this is the text.
            */
            image.drawText(text, [x, y - 20], options);
        });

        /*
        To get the dataURL for our image, we call its <code>src()</code>
        method, and to put it in the DOM, we use Ox.$, which is similar to
        jQuery's <code>$</code>.
        */
        Ox.$('<img>').attr({src: image.src()}).appendTo(Ox.$('body'));

    });

});
