/*
command: phonegap analytics

when: user has opted in
result: outputs message "Analytics is enabled! Nice, you are helping us make phonegap tooling better."
"If you would like to turn analytics off, simply run `phonegap analytics off`

when: user has opted out
result: outputs message "Analytics is off. If you would like to enable analytics simply run `phonegap analytics on`"

when: user has not specified anything yet
result: user is presented with y/n option to explicitely turn it on or off

commands:
phonegap analytics reset|on|off
*/

var Insight = require('insight');
var Configstore = require('configstore');
var fs = require('fs');
var path = require('path');
var request = require('request');
var sanitizeArgs = require('./util/sanitize-args');
var os_name = require('os-name');
var util = require('util');

// Google Analytics tracking code
var trackingCode = 'UA-94271-37'; // this is the default production tracking code

var rootPath = require.resolve('../../package.json');
var gitPath = path.join(path.dirname(rootPath),'.git');
if(fs.existsSync(gitPath)) {
    // set it to the dev tracking code
    trackingCode = 'UA-94271-38';
}
var pkg_json = require('../../package.json');

var insight = new Insight({
    "trackingCode": trackingCode,
    "pkg": pkg_json
});

var PromptPreamble = '\nHow you use PhoneGap provides us with important data that we can use to make\n' +
                     'our products better. Please read our privacy policy for more information on the\n' +
                     'data we collect. http://www.adobe.com/privacy.html';
var PromptMessage = 'Would you like to allow PhoneGap to collect anonymous usage data?';
var AnalyticsOffMessage  = '\nAnalytics is off. \nIf you would like to turn analytics on, simply run `phonegap analytics on`\n';
var AnalyticsOnMessage  = '\nAnalytics is on! Nice, you are helping us improve PhoneGap tooling.\n' +
                         'If you would like to turn analytics off, simply run `phonegap analytics off`\n';

/*
    Helper function to determine if cli is a production/dev release
*/

function getEnvironment(package_json) {
    if(/cordova/.test(package_json.version)) {
        return 1;
    } else {
        return 0;
    }
}


/*
    Helper function to send events to the analytics end point
*/
function sendAnalytics(data) {
    if (!data) return;

    request.post({
        url: 'https://metrics.phonegap.com/gelf',
        form: JSON.stringify(data)
    }, function(err, res, body) {
        // TODO: do we want to report errors to somewhere???
        if (err && err.code == 'ETIMEDOUT') {
            // We had a timeout! oh no.
            if (err.connect) {
                // this was a connection timeout, meaning, we timed out
                // establishing a connection to metrics.phonegap.com
            } else {
                // this was a read timeout, meaning, we timed out waiting for a
                // response from the server
            }
        }
    });
}

module.exports = function analytics(argv, callback) {
    var params = argv._.slice(1);

    if (params.length > 0) {
        switch(params[0].toLowerCase()) {
            case "on" :
                // only track it if the value is changing
                if (insight.optOut !== false) {
                    // must change it before we use it
                    insight.optOut = false;
                    module.exports.trackEvent(argv._);
                }
                break;
            case "off" :
                // track it only if it changes
                if (insight.optOut !== true) {
                    // must use it before we change it
                    module.exports.trackEvent(argv._);
                    insight.optOut = true;
                }
                break;
            case "reset" :
                // this is a secret api, mainly just for testing the prompt messages
                console.log("resetting it .. ");
                insight.optOut = undefined;
                break;
        }
    }
    if (insight.optOut === undefined) {
    } else {
        // somewhat confusing tri-state, it could be true|false|undefined
        if (insight.optOut) {
            console.log(AnalyticsOffMessage);
        }
        else {
            console.log(AnalyticsOnMessage);
        }
    }
    callback();
};

var EVENT_EXPIRY_TIME = 30 * 60 * 1000; // 30 minutes in milliseconds
module.exports.EVENT_EXPIRY_TIME = EVENT_EXPIRY_TIME;
// Use the same underlying filesystem config object that the `Insight` module
// above uses. This way we hopefully don't litter config objects everywhere.
var config = new Configstore('insight-phonegap');
module.exports.config = config;
/*
    Helper function to help build up GELF formatted json
*/

function basicGELF() {
    var event = {
        "version": "1.1",
        "host": "cli",
        "short_message": "",
        "_userID": insight.clientId,
        "_session": true,
        "_appVersion": pkg_json.version,
        "_nodeVersion": process.version,
        "_platform": os_name(),
        "_env": getEnvironment(pkg_json)
    };
    var now = (new Date()).valueOf(); // in ms
    var lastRun = config.get('lastRun');
    if (lastRun && (now - lastRun < EVENT_EXPIRY_TIME)) {
        // If the CLI ran consecutive actions within the expiry time, use the same session id.
        event["_session"] = lastRun;
    } else {
        event["_session"] = now;
        config.set('lastRun', now);
    }
    return event;
}
module.exports.hasOptedOut = function hasOptedOut() {
    return insight.optOut === true;
};


module.exports.prompt = function prompt(callback) {
    console.log(PromptPreamble);

    insight.askPermission(PromptMessage,function(error,optIn) {
        if (optIn) {
            // user has accepted, we will thank them and track this
            insight.trackEvent({"category":"analytics-prompt",
                                "action":"accepted",
                                "label":""});

            var info = basicGELF();
            info.short_message = "analytics-prompt accepted";
            sendAnalytics(info);

            console.log(AnalyticsOnMessage);
        }
        else {
            // user has declined, we still want to track this
            insight.optOut = false;
            insight.trackEvent({"category":"analytics-prompt",
                                "action":"declined",
                                "label":""});

            var info = basicGELF();
            info.short_message = "analytics-prompt declined";
            sendAnalytics(info);

            insight.optOut = true;
            console.log(AnalyticsOffMessage);
        }
        callback();
    });
};

module.exports.statusUnknown = function statusUnknown() {
    return insight.optOut === undefined;
};

/**
 * Given a set of arguments passed to the CLI, optional error object, and
 * optional event overrides, combine all parameters into an event object
 * suitable for use in tracking for analytics.
 *
 * @param  {string[]} args [command line arguments passed to the cli]
 * @param  {Object} error   [optional object representing an error that occurred] (optional)
 * @param  {Object} overrides   [properties in this object will override whatever exists in the final analytics event object] (optional)
 */
module.exports.trackEvent = function trackEvent(args, error, overrides) {
    // if we received an error, then we will exit with an error status
    // if an exit code was attached to the error, then use it
    // otherwise default to 1.
    var exitCode = error ? error.exitCode || 1 : 0;
    var cleanedResult = sanitizeArgs.stringifyForGoogleAnalytics(args);
    var category = cleanedResult.command;
    var action = cleanedResult.params;
    var label = exitCode + "";
    var value = cleanedResult.count;
    if (module.exports.hasOptedOut() === false) {
        if (cleanedResult.command) {
            // If we have a command parsed out, send it off to metrics
            var info = basicGELF();
            info.short_message = sanitizeArgs.getCommand(args);
            info._flags = sanitizeArgs.getSwitches(args);
            info._exitCode = exitCode;
            info._params = sanitizeArgs.filterParameters(args);
            if (error) {
                if (error.stack) info._error_stack = error.stack;
                if (error.output) info._error_msg = error.output;
                if (error.message) info._error_msg = error.message;
            }
            if (overrides) {
                info = util._extend(info, overrides);
            }
            sendAnalytics(info);
        }
        category = category || "-";
        action = action || "-";
        label = label || "-";
        value = value || 0;
        insight.trackEvent({"category":category,
                            "action":action,
                            "label":label,
                            "value":value});
    }
};
