// earthquakes_live.js
//
// exploratory implementation in prep for abstract latlong to earth graphing tool for VR
// shows all of the quakes in the past 24 hours reported by the USGS
//
// created by james b. pollack @imgntn on 12/5/2015
//  Copyright 2015 High Fidelity, Inc.
//  Distributed under the Apache License, Version 2.0.
//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// working notes: maybe try doing markers as boxes,rotated to the sphere normal, and with the height representing some value

Script.include('../libraries/promise.js');
var Promise = loadPromise();

Script.include('../libraries/tinyColor.js');
var tinyColor = loadTinyColor();

//you could make it the size of the actual earth. 
var EARTH_SPHERE_RADIUS = 6371;
var EARTH_SPHERE_RADIUS = 2;

var EARTH_CENTER_POSITION = Vec3.sum(Vec3.sum(MyAvatar.position, {
    x: 0,
    y: 0.5,
    z: 0
}), Vec3.multiply(EARTH_SPHERE_RADIUS, Quat.getFront(Camera.getOrientation())));

var EARTH_MODEL_URL = 'http://hifi-content.s3.amazonaws.com/james/earthquakes_live/models/earth-noclouds.fbx';

var SHOULD_SPIN=false;
var POLL_FOR_CHANGES = true;
//USGS updates the data every five minutes
var CHECK_QUAKE_FREQUENCY = 5 * 60 * 1000;

var QUAKE_MARKER_DIMENSIONS = {
    x: 0.01,
    y: 0.01,
    z: 0.01
};

function createEarth() {
    var earthProperties = {
        name: 'Earth',
        type: 'Model',
        modelURL: EARTH_MODEL_URL,
        position: EARTH_CENTER_POSITION,
        dimensions: {
            x: EARTH_SPHERE_RADIUS,
            y: EARTH_SPHERE_RADIUS,
            z: EARTH_SPHERE_RADIUS
        },
        rotation: Quat.fromPitchYawRollDegrees(0, 90, 0),
        // dynamic: true,
        //if you have a shapetype it blocks the smaller markers
        // shapeType:'sphere'
        // userData: JSON.stringify({
        //     grabbableKey: {
        //         grabbable: false
        //     }
        // })
    }

    return Entities.addEntity(earthProperties)
}

function latLongToVector3(lat, lon, radius, height) {
    var phi = (lat) * Math.PI / 180;
    var theta = (lon - 180) * Math.PI / 180;

    var x = -(radius + height) * Math.cos(phi) * Math.cos(theta);
    var y = (radius + height) * Math.sin(phi);
    var z = (radius + height) * Math.cos(phi) * Math.sin(theta);

    return {
        x: x,
        y: y,
        z: z
    };
}

function getQuakePosition(earthquake) {
    var longitude = earthquake.geometry.coordinates[0];
    var latitude = earthquake.geometry.coordinates[1];
    var depth = earthquake.geometry.coordinates[2];

    var latlng = latLongToVector3(latitude, longitude, EARTH_SPHERE_RADIUS / 2, 0);

    var position = EARTH_CENTER_POSITION;
    var finalPosition = Vec3.sum(position, latlng);

    //print('finalpos::' + JSON.stringify(finalPosition))
    return finalPosition
}

var QUAKE_URL = 'http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson'

function get(url) {
    print('getting' + url)
        // Return a new promise.
    return new Promise(function(resolve, reject) {
        // Do the usual XHR stuff
        var req = new XMLHttpRequest();
        req.open('GET', url);
        req.onreadystatechange = function() {
            print('req status:: ' + JSON.stringify(req.status))

            if (req.readyState == 4 && req.status == 200) {
                var myArr = JSON.parse(req.responseText);
                resolve(myArr);
            }
        };

        req.send();
    });
}

function createQuakeMarker(earthquake) {
    var markerProperties = {
        name: earthquake.properties.place,
        type: 'Sphere',
        parentID:earth,
        dimensions: QUAKE_MARKER_DIMENSIONS,
        position: getQuakePosition(earthquake),
        collisionless:true,
        lifetime: 6000,
        color: getQuakeMarkerColor(earthquake)
    }

    //  print('marker properties::' + JSON.stringify(markerProperties))
    return Entities.addEntity(markerProperties);
}

function getQuakeMarkerColor(earthquake) {
    var color = {};
    var magnitude = earthquake.properties.mag;
    //realistic but will never get full red coloring and will probably be pretty dull for most.  must experiment
    var sValue = scale(magnitude, 0, 10, 0, 100);
    var HSL_string = "hsl(0, " + sValue + "%, 50%)"
    var color = tinyColor(HSL_string);
    var finalColor = {
        red: color._r,
        green: color._g,
        blue: color._b
    }

    return finalColor
}

function scale(value, min1, max1, min2, max2) {
    return min2 + (max2 - min2) * ((value - min1) / (max1 - min1));
}

function processQuakes(earthquakes) {
    print('quakers length' + earthquakes.length)
    earthquakes.forEach(function(quake) {
        // print('PROCESSING A QUAKE')
        var marker = createQuakeMarker(quake);
        markers.push(marker);
    })
    print('markers length:' + markers.length)
}

var quakes;
var markers = [];

var earth = createEarth();

function getThenProcessQuakes() {
    get(QUAKE_URL).then(function(response) {
        print('got it::' + response.features.length)
        quakes = response.features;
        processQuakes(quakes);
        //print("Success!" + JSON.stringify(response));
    }, function(error) {
        print('error getting quakes')
    });
}

function cleanupMarkers() {
    print('CLEANING UP MARKERS')
    while (markers.length > 0) {
        Entities.deleteEntity(markers.pop());
    }
}

function cleanupEarth() {
    Entities.deleteEntity(earth);
    Script.update.disconnect(spinEarth);
}

function cleanupInterval() {
    if (pollingInterval !== null) {
        Script.clearInterval(pollingInterval)
    }
}

Script.scriptEnding.connect(cleanupMarkers);
Script.scriptEnding.connect(cleanupEarth);
Script.scriptEnding.connect(cleanupInterval);

getThenProcessQuakes();

var pollingInterval = null;

if (POLL_FOR_CHANGES === true) {
    pollingInterval = Script.setInterval(function() {
        cleanupMarkers();
        getThenProcessQuakes()
    }, CHECK_QUAKE_FREQUENCY)
}


function spinEarth(){
Entities.editEntity(earth,{
    angularVelocity:{
        x:0,
        y:0.25,
        z:0
    }
})
}

if(SHOULD_SPIN===true){
    Script.update.connect(spinEarth);
}