var Clay = require('pebble-clay');
var clayConfig = require('./config');
var clay = new Clay(clayConfig, null, { autoHandleEvents: false });
var messageKeys = require('message_keys');

Pebble.addEventListener('showConfiguration', function(e) {

    // This is an example of how you might load a different config based on platform.
    var platform = clay.meta.activeWatchInfo.platform || 'aplite';
    if (platform === 'aplite') {
        clay.config = clayConfigAplite;
    }

    Pebble.openURL(clay.generateUrl());
});

Pebble.addEventListener('webviewclosed', function(e) {
    if (!t || t.response) {
        try {
            if (data = JSON.parse(t.response), data.strava) {
                //data.strava will be like this :
                // {"code":"db896b06f89804997a8088320fba755e6299c0d6","scope":"read,activity:write","state":"bike_companion"}
                // so need to parse it correctly
                //console.log("strava temp code to exchange to access token : " + data.code)
                // placeholder to get token from code from php
                return token
            }
        } catch (t) {
            i && console.error("Parsing error:", t)
        }
        var dict = clay.getSettings(t.response);

        /* assess if needed to send setting to watch as already in phone (done with "getsettings")
        m.live_mmt_enable = dict[p.live_mmt_enable]
        m.live_mmt_login = dict[p.live_mmt_login]
        m.live_mmt_password = dict[p.live_mmt_password]
        m.live_jayps_enable = dict[p.live_jayps_enable]
        m.live_jayps_login = dict[p.live_jayps_login]
        m.live_jayps_password = dict[p.live_jayps_password]
        m.strava_automatic_upload = dict[p.strava_automatic_upload]
    
        i = dict[p.debug]
        console.log("debug:" + i)
        g.setDebug(i)
        h.setDebug(i)
        b.setDebug(i)
        y.setDebug(i)
        m.setDebug(i)
    
        m.save()
        // Assess if needed to send settings values to watch side
        /*
        Pebble.sendAppMessage(dict, function(e) {
            console.log('Sent config data to Pebble');
        }, function(e) {
            console.log('Failed to send config data!');
            console.log(JSON.stringify(e));
        });*/
    }
});


var message;
var gpx_to_strava
var gpx_to_web
var locate_me

var locationInterval;
var instantLocationInterval;

var firstlocationOptions = {
    'enableHighAccuracy': true, // default = false (quick and dirty mode), can be true (more accurate but need more power and time)
    'timeout': 60000, //60s timeout to get a first good signal
    'maximumAge': 0 // no cache
};
var locationOptions = {
    'enableHighAccuracy': true, // default = false (quick and dirty mode), can be true (more accurate but need more power and time)
    'timeout': 5000, //5s timeout to get a good signal
    'maximumAge': 0 // no cache
};
var geoloc_id;

// Store location in Pebble app local storage
//
function storeLocation(position) {
    var latitude = position.coords.latitude;
    var longitude = position.coords.longitude;
    var timestamp = position.timestamp;
    localStorage.setItem("latitude", latitude);
    localStorage.setItem("longitude", longitude);
    localStorage.setItem("timestamp", timestamp);
    // console.log("Stored location " + position.coords.latitude + ',' + position.coords.longitude);
}

// Get location from Pebble app local storage
//
function getLocation() {
    if (localStorage.getItem("latitude") || localStorage.getItem("longitude") || localStorage.getItem("timestamp")) {
        var la = localStorage.getItem("latitude");
        var lo = localStorage.getItem("longitude");
        var ti = localStorage.getItem("timestamp");
        var co = { "latitude": la, "longitude": lo };
        var pos = { "coords": co, "timestamp": ti };
        // console.log("Stored location " + pos.co.la + ',' + pos.co.lo);
        return pos;
    } else {
        return null;
    }
}

// Get max speed of the run
//
function getMaxSpeed(lastSpeed) {
    oldmax = localStorage.getItem("maxSpeed") || -1;
    if (oldmax < lastSpeed) {
        maxSpeed = lastSpeed
    } else if (oldmax > lastSpeed) {
        maxSpeed = oldmax
    } else {
        maxSpeed = oldmax
    }
    localStorage.setItem("maxSpeed", maxSpeed);
    return maxSpeed
}

// split float number into an array of int (null returned instead of 0 for decimal)
//
function splitFloatNumber(num) {
    const intStr = num.toString().split('.')[0];
    const decimalStr = num.toString().split('.')[1];
    return [Number(intStr), Number(decimalStr)];

}

// Build GPX headers
//
function GPXHeadersBuilder(timestamp, name, type) {
    var headers = '<?xml version="1.0" encoding="UTF-8"?><gpx creator="Pebble with barometer" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" version="1.1" xmlns="http://www.topografix.com/GPX/1/1"><metadata><time>' + timestamp + '</time></metadata><trk><name>' + name + '</name><type>' + type + '</type><trkseg>';
    var ret = localStorage.setItem("GPX", headers);
    return true;
}

// Build GPX footer
//
function GPXtrkptBuilder(lat, lon, ele, timestamp) {
    var GPX = localStorage.getItem("GPX");
    var trkpt = '<trkpt lat="' + lat + '" lon="' + lon + '"><ele>' + ele + '</ele><time>' + timestamp + '</time></trkpt>';
    localStorage.setItem("GPX", GPX + trkpt);
    return true;
}

// Build GPX footer
//
function GPXfooterBuilder() {
    var GPX = localStorage.getItem("GPX");
    var footer = '</trkseg></trk></gpx>';
    var ret = localStorage.setItem("GPX", GPX + footer);
    //console.log("GPX closed : " + GPX + footer);
    return ret;
}


// Send GPX to Strava profile
// TODO : get authentication creds from settings
function SendToStrava() {
    console.log('--- GPX upload to strava');
    var gpxfile = localStorage.getItem("GPX");
    // need to automate oAUTH
    var bearer = "09f93068353f11f09d22059f1e8e42ef526949a5"
    params = {
        url: "https://www.strava.com/api/v3/uploads",
        method: "POST",
        data: { description: "desc", data_type: "gpx" },
        files: { file: gpxfile },
        authorization: "Bearer " + bearer,
        callback: function(e) {
            var message = "";
            // what is 'r'
            // what is 'e'
            // what is 'o'
            // what is 'z'
            if (console.log(e.status + " - " + e.txt), 201 == e.status) {
                message = "Your activity has been created";
            } else if (400 == e.status) {
                message = "An error has occurred. If you've already uploaded the current activity, please delete it in Strava.";
            } else if (401 == e.status) {
                message = "Error - Unauthorized. Please check your credentials in the settings.", o.setAccessToken("");
            } else {
                try {
                    response_json = JSON.parse(e.txt)
                    response_json.error ? (console.log("error:" + response_json.error), message = response_json.error, o.setAccessToken("")) : response_json.status && (console.log("status:" + response_json.status), z = response_json.status)
                } catch (e) {
                    console.log("Error log, " + e)
                }
            }
            message && Pebble.showSimpleNotificationOnPebble("Ventoo SE - Strava", message)
        }
    }
    var XHR = new XMLHttpRequest;
    var n = this;
    console.log(params.url);
    XHR.open(params.method, params.url, !0);
    var body = "";
    var boundary = Math.random().toString().substring(2);
    XHR.setRequestHeader("content-type", "multipart/form-data; charset=utf-8; boundary=" + boundary)
    XHR.setRequestHeader("Authorization", params.authorization);
    for (var i in params.data) body += "--" + boundary + '\r\nContent-Disposition: form-data; name="' + i + '"\r\n\r\n' + params.data[i] + "\r\n";
    for (var i in params.files) body += "--" + boundary + '\r\nContent-Disposition: form-data; name="' + i + '" ; filename=test.gpx\r\n\r\n' + params.files[i] + "\r\n";
    body += "--" + boundary + "--\r\n"

    XHR.onreadystatechange = function() {
        // what is 'n'
        try {
            4 == XHR.readyState && (n.status = XHR.status, n.txt = XHR.responseText, n.xml = XHR.responseXML, params.callback && params.callback(n))
        } catch (e) {
            console.error("Error2 loading, ", e)
        }
    }
    XHR.send(body)
}


// Send GPX to web server (need configuration on serverside)
// TODO : secure it ?
function PostToWeb() {
    console.log('--- GPX upload to custom web server');
    var GPX = localStorage.getItem("GPX");
    var url = JSON.parse(localStorage.getItem('clay-settings')).gpx_web_url + "?name=pebblegpx&type=application/gpx+xml";
    var xhr = new XMLHttpRequest();
    xhr.timeout = 10000; // time in milliseconds

    xhr.open("POST", url, false);

    //console.log('------ CSV / xhr opened')
    xhr.onload = function() {
        //console.log('------xhr onload')
        if (xhr.readyState === 4) {
            //console.log('------xhr request returned with ' + xhr.status);
            //console.log(this.responseText);
            if (xhr.status == 200) {
                //console.log('--> HTTP 200');
                return true;
            } else {
                //console.log('--> HTTP ' + xhr.status);
                return false;
            }
        }
    };

    //send CSV in body
    xhr.send(GPX);

}

// Send location to web server for instant location (no live tracking)
// TODO : secure it ?
function instantLocationUpdate(pos) {
    console.log('--- Instant location update');
    // console.log(" location is " + new_pos.coords.latitude + ',' + new_pos.coords.longitude + ' , acc. ' + new_pos.coords.accuracy);

    var url = JSON.parse(localStorage.getItem('clay-settings')).ping_location_url + "?lat=" + pos.coords.latitude + "&long=" + pos.coords.longitude + "&acc=" + pos.coords.accuracy + "&timestamp=" + pos.timestamp;
    var xhr = new XMLHttpRequest();
    xhr.timeout = 10000; // time in milliseconds

    xhr.open("POST", url);

    //console.log('------ instant / xhr opened')
    xhr.onload = function() {
        //console.log('------xhr onload')
        if (xhr.readyState === 4) {
            //console.log('------xhr request returned with ' + xhr.status);
            //console.log(this.responseText);
            if (xhr.status == 200) {
                //console.log('--> HTTP 200');
                return true;
            } else {
                //console.log('--> HTTP ' + xhr.status);
                return false;
            }
        }
    };

    //send without body
    xhr.send();

}

// called in case of successful geoloc gathering and sends the coordinate to watch
//
function locationSuccess(new_pos) {
    console.log('--- locationSuccess');
    // console.log(" location is " + new_pos.coords.latitude + ',' + new_pos.coords.longitude + ' , acc. ' + new_pos.coords.accuracy);

    var prev_pos = getLocation();
    storeLocation(new_pos);
    if (prev_pos === null) {
        console.log('--- start building gpx');

        if (gpx_to_strava || gpx_to_web) {
            // Start the GPX file
            GPXHeadersBuilder(new Date(new_pos.timestamp).toISOString(), "test", "18");
        }
    } else {
        //clear watch of new position to avoid overlap
        //navigator.geolocation.clearWatch(geoloc_id);
        //console.log('--- watch geoloc cleared');
        //var speed = speed_from_distance_and_time(prev_pos, new_pos);

        //get speed from geoloc API isntead of calculate it
        // speed is initially in m/s, get it at km/h
        if (new_pos.coords.speed === null) {
            var speed = 0;
        } else {
            var speed = new_pos.coords.speed * 3.6;
        }

        // Prepare display on watch
        // now it's only raw data
        // init strings
        var latitudeString = "";
        var longitudeString = "";
        var accuracyString = "";
        var altitudeString = "";
        var speedString = "";

        //formating for precision and max size
        latitudeString = new_pos.coords.latitude.toString().substring(0, 12);
        longitudeString = new_pos.coords.longitude.toString().substring(0, 12);
        accuracyString = new_pos.coords.accuracy.toString().substring(0, 4);
        //console.log("split num : " + new_pos.coords.altitude);
        altitudeString = splitFloatNumber(new_pos.coords.altitude)[0].toString().substring(0, 5);
        timestampISO = new Date(new_pos.timestamp).toISOString();
        //console.log("split num : " + speed);
        if (isNaN(speed)) {
            speedString = "---";
        } else {
            speedString = splitFloatNumber(speed)[0].toString().substring(0, 3) + "." + splitFloatNumber(speed)[1].toString().substring(0, 1);
            if (speedString == "0.N") {
                speedString = "0.0";
            }

            //console.log("split num : " + getMaxSpeed(speed));
            maxSpeedString = splitFloatNumber(getMaxSpeed(speed))[0].toString().substring(0, 3);
        }

        if (gpx_to_strava || gpx_to_web) {
            //add a new datapoint to GPX file
            GPXtrkptBuilder(latitudeString, longitudeString, altitudeString, timestampISO);

        }

        // Build message
        message = "OK";
        var dict = {
            'accuracy': accuracyString,
            'altitude': altitudeString,
            'speed': speedString,
            'max_speed': maxSpeedString,
            'status': message
        };

        // Send the message
        Pebble.sendAppMessage(dict, function() {
            console.log('Message sent successfully: ' + JSON.stringify(dict));
        }, function(e) {
            console.log('Message (' + JSON.stringify(dict) + ') failed: ' + JSON.stringify(e));
        });
    }

}

function locationError(err) {

    console.warn('location error (' + err.code + '): ' + err.message);

}


function get_coordinate() {
    console.log('--- Starting regular getCurrentPosition loop using setInterval at 1 sec');

    locationInterval = setInterval(function() {
        navigator.geolocation.getCurrentPosition(locationSuccess, locationError, locationOptions);
    }, 1000);

    if (locate_me) {
        instantLocationInterval = setInterval(function() {
            navigator.geolocation.getCurrentPosition(instantLocationUpdate, locationError, locationOptions);
        }, 60000);
    }

}

function init() {
    // local storage init
    gpx_to_strava = JSON.parse(localStorage.getItem('clay-settings')).strava_upload;
    gpx_to_web = JSON.parse(localStorage.getItem('clay-settings')).gpx_web_enable;
    locate_me = JSON.parse(localStorage.getItem('clay-settings')).ping_location_enable;

    var ce = gpx_to_web;
    var cu = localStorage.getItem("custom_enabled");
    var se = gpx_to_strava;
    var su = localStorage.getItem("strava_enabled");

    if ((se && !su) || (ce && !cu)) {
        //posting any missed XHR from previous ride session
        if (ce) {
            PostToWeb();
        }
        if (se) {
            SendToStrava();
        }
    } else {
        localStorage.setItem("GPX", "");
        localStorage.setItem("maxSpeed", "");
        localStorage.setItem("latitude", "");
        localStorage.setItem("longitude", "");
        localStorage.setItem("timestamp", "");
        localStorage.setItem("custom_uploaded", false);
        localStorage.setItem("strava_uploaded", false);
    }
    // clear any other var to do
    clearInterval(locationInterval);
    clearInterval(instantLocationInterval);
    navigator.geolocation.getCurrentPosition(locationSuccess, locationError, firstlocationOptions);

}

// Get JS readiness events
Pebble.addEventListener('ready', function(e) {
    console.log('PebbleKit JS is ready');
    // Update Watch on this
    Pebble.sendAppMessage({ 'JSReady': 1 });

    init();
});

// Get AppMessage events
Pebble.addEventListener('appmessage', function(e) {
    // Get the dictionary from the message
    var dict = e.payload;
    //console.log(dict[0].toString());
    switch (dict[0]) {
        case 'get':
            get_coordinate();
            break;
        case 'exit':
            clearInterval(instantLocationInterval);
            clearInterval(locationInterval);
            if (gpx_to_strava || gpx_to_web) {
                //End GPX file
                GPXfooterBuilder();
                if (gpx_to_strava) {
                    //send to strava through API
                    SendToStrava();
                }
                if (gpx_to_web) {
                    // send CSV to web server through API
                    PostToWeb();
                }
            }
            // Send the message
            var dict = {
                'status': "EXIT"
            };
            Pebble.sendAppMessage(dict, function() {
                console.log('Message sent successfully: ' + JSON.stringify(dict));
            }, function(e) {
                console.log('Message (' + JSON.stringify(dict) + ') failed: ' + JSON.stringify(e));
            });

            break;
        default:
            console.log('Sorry. I don\'t understand your request :' + dict[0]);
    }

});