"use strict";
var stubs_1 = require("./stubs");
var yok_1 = require("../../yok");
var analytics_service_1 = require("../../services/analytics-service");
var Future = require("fibers/future");
var os = require("os");
var helpersLib = require("../../helpers");
var host_info_1 = require("../../host-info");
var assert = require("chai").assert;
var trackedFeatureNamesAndValues = "";
var savedSettingNamesAndValues = "";
var lastTrackedExceptionMsg = "";
var lastUsedEqatecSettings;
var isEqatecStopCalled = false;
require("../../vendor/EqatecMonitor.min");
var originalEqatec = global._eqatec;
function setGlobalEqatec(shouldSetUserThrowException, shouldStartThrow) {
    global._eqatec = {
        createSettings: function (apiKey) {
            return {};
        },
        createMonitor: function (settings) {
            lastUsedEqatecSettings = settings;
            return {
                trackFeature: function (featureNameAndValue) {
                    trackedFeatureNamesAndValues += featureNameAndValue + os.EOL;
                },
                trackException: function (exception, message) {
                    lastTrackedExceptionMsg = message;
                },
                stop: function () { isEqatecStopCalled = true; },
                setInstallationID: function (guid) { },
                setUserID: function (userId) {
                    if (shouldSetUserThrowException) {
                        throw new Error("setUserID throws");
                    }
                },
                start: function () {
                    if (shouldStartThrow) {
                        throw new Error("start throws");
                    }
                },
                setStartCount: function (count) { },
                status: function () { return ({ isSending: false }); }
            };
        },
    };
}
var UserSettingsServiceStub = (function () {
    function UserSettingsServiceStub(featureTracking, exceptionsTracking, testInjector) {
        this.featureTracking = featureTracking;
        this.exceptionsTracking = exceptionsTracking;
        this.testInjector = testInjector;
    }
    UserSettingsServiceStub.prototype.getSettingValue = function (settingName) {
        var _this = this;
        return (function () {
            var $staticConfig = _this.testInjector.resolve("staticConfig");
            if (settingName === $staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME) {
                return _this.featureTracking !== undefined ? _this.featureTracking.toString() : undefined;
            }
            else if (settingName === $staticConfig.ERROR_REPORT_SETTING_NAME) {
                return _this.exceptionsTracking !== undefined ? _this.exceptionsTracking.toString() : undefined;
            }
            return undefined;
        }).future()();
    };
    UserSettingsServiceStub.prototype.saveSetting = function (key, value) {
        return (function () {
            savedSettingNamesAndValues += key + "." + value;
        }).future()();
    };
    return UserSettingsServiceStub;
})();
function createTestInjector(testScenario) {
    setGlobalEqatec(testScenario.shouldSetUserThrowException, testScenario.shouldStartThrow);
    var testInjector = new yok_1.Yok();
    testInjector.register("logger", stubs_1.CommonLoggerStub);
    testInjector.register("errors", stubs_1.ErrorsStub);
    testInjector.register("analyticsService", analytics_service_1.AnalyticsService);
    testInjector.register("analyticsSettingsService", {
        canDoRequest: function () {
            return Future.fromResult(testScenario.canDoRequest);
        },
        getClientName: function () {
            return "UnitTests";
        },
        getPrivacyPolicyLink: function () {
            return "privacy policy link";
        },
        getUserId: function () {
            return Future.fromResult("UnitTestsUserId");
        },
        getUserSessionsCount: function () { return Future.fromResult(0); },
        setUserSessionsCount: function (count) { return Future.fromResult(); }
    });
    testInjector.register("options", {
        analyticsClient: null
    });
    testInjector.register("prompter", {
        confirm: function (message, defaultAction) {
            return Future.fromResult(testScenario.prompterConfirmResult);
        }
    });
    testInjector.register("staticConfig", {
        ERROR_REPORT_SETTING_NAME: "TrackExceptions",
        TRACK_FEATURE_USAGE_SETTING_NAME: "TrackFeatureUsage",
        CLIENT_NAME: "common-lib",
        ANALYTICS_API_KEY: "AnalyticsAPIKey"
    });
    testInjector.register("hostInfo", host_info_1.HostInfo);
    testInjector.register("userSettingsService", new UserSettingsServiceStub(testScenario.featureTracking, testScenario.exceptionsTracking, testInjector));
    testInjector.register("progressIndicator", {
        showProgressIndicator: function (future, timeout, options) {
            return future;
        }
    });
    helpersLib.isInteractive = function () {
        return testScenario.isInteractive;
    };
    return testInjector;
}
describe("analytics-service", function () {
    var baseTestScenario;
    var featureName = "unit tests feature";
    var service = null;
    beforeEach(function () {
        baseTestScenario = {
            canDoRequest: true,
            featureTracking: true,
            exceptionsTracking: true,
            isInteractive: true,
            prompterConfirmResult: true,
            shouldSetUserThrowException: false,
            shouldStartThrow: false
        };
        trackedFeatureNamesAndValues = "";
        lastTrackedExceptionMsg = "";
        savedSettingNamesAndValues = "";
        isEqatecStopCalled = false;
        lastUsedEqatecSettings = {};
        service = null;
    });
    afterEach(function () {
        if (service) {
            service.tryStopEqatecMonitor();
        }
    });
    after(function () {
        global._eqatec = originalEqatec;
    });
    describe("trackFeature", function () {
        it("tracks feature when console is interactive", function () {
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.trackFeature(featureName).wait();
            assert.isTrue(trackedFeatureNamesAndValues.indexOf("CLI." + featureName) !== -1);
            service.tryStopEqatecMonitor();
        });
        it("tracks feature when console is not interactive", function () {
            baseTestScenario.isInteractive = false;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.trackFeature(featureName).wait();
            assert.isTrue(trackedFeatureNamesAndValues.indexOf("Non-interactive." + featureName) !== -1);
            service.tryStopEqatecMonitor();
        });
        it("does not track feature when console is interactive and feature tracking is disabled", function () {
            baseTestScenario.featureTracking = false;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.trackFeature(featureName).wait();
            assert.deepEqual(trackedFeatureNamesAndValues, "");
        });
        it("does not track feature when console is not interactive and feature tracking is disabled", function () {
            baseTestScenario.featureTracking = baseTestScenario.isInteractive = false;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.trackFeature(featureName).wait();
            assert.deepEqual(trackedFeatureNamesAndValues, "");
        });
        it("does not track feature when console is interactive and feature tracking is enabled, but cannot make request", function () {
            baseTestScenario.canDoRequest = false;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.trackFeature(featureName).wait();
            assert.deepEqual(trackedFeatureNamesAndValues, "");
        });
        it("does not track feature when console is not interactive and feature tracking is enabled, but cannot make request", function () {
            baseTestScenario.canDoRequest = baseTestScenario.isInteractive = false;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.trackFeature(featureName).wait();
            assert.deepEqual(trackedFeatureNamesAndValues, "");
        });
        it("does not throw exception when eqatec start throws", function () {
            baseTestScenario.shouldStartThrow = true;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.trackFeature(featureName).wait();
            assert.deepEqual(trackedFeatureNamesAndValues, "");
        });
    });
    describe("trackException", function () {
        var exception = "Exception";
        var message = "Track Exception Msg";
        it("tracks when all conditions are correct", function () {
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.trackException(exception, message).wait();
            assert.isTrue(lastTrackedExceptionMsg.indexOf(message) !== -1);
        });
        it("does not track when exception tracking is disabled", function () {
            baseTestScenario.exceptionsTracking = false;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.trackException(exception, message).wait();
            assert.deepEqual(lastTrackedExceptionMsg, "");
        });
        it("does not track when feature tracking is enabled, but cannot make request", function () {
            baseTestScenario.canDoRequest = false;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.trackException(exception, message).wait();
            assert.deepEqual(lastTrackedExceptionMsg, "");
        });
        it("does not throw exception when eqatec start throws", function () {
            baseTestScenario.shouldStartThrow = true;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.trackException(exception, message).wait();
            assert.deepEqual(lastTrackedExceptionMsg, "");
        });
    });
    describe("track", function () {
        var name = "unitTests";
        it("tracks when all conditions are correct", function () {
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.track(name, featureName).wait();
            assert.isTrue(trackedFeatureNamesAndValues.indexOf(name + "." + featureName) !== -1);
        });
        it("does not track when feature tracking is disabled", function () {
            baseTestScenario.featureTracking = false;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.track(name, featureName).wait();
            assert.deepEqual(trackedFeatureNamesAndValues, "");
        });
        it("does not track when feature tracking is enabled, but cannot make request", function () {
            baseTestScenario.canDoRequest = false;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.track(name, featureName).wait();
            assert.deepEqual(trackedFeatureNamesAndValues, "");
        });
        it("does not throw exception when eqatec start throws", function () {
            baseTestScenario.shouldStartThrow = true;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.track(name, featureName).wait();
            assert.deepEqual(trackedFeatureNamesAndValues, "");
        });
    });
    describe("isEnabled", function () {
        it("returns true when analytics status is enabled", function () {
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            var staticConfig = testInjector.resolve("staticConfig");
            assert.isTrue(service.isEnabled(staticConfig.ERROR_REPORT_SETTING_NAME).wait());
            assert.isTrue(service.isEnabled(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME).wait());
        });
        it("returns false when analytics status is disabled", function () {
            baseTestScenario.exceptionsTracking = baseTestScenario.featureTracking = false;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            var staticConfig = testInjector.resolve("staticConfig");
            assert.isFalse(service.isEnabled(staticConfig.ERROR_REPORT_SETTING_NAME).wait());
            assert.isFalse(service.isEnabled(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME).wait());
        });
        it("returns false when analytics status is notConfirmed", function () {
            baseTestScenario.exceptionsTracking = baseTestScenario.featureTracking = undefined;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            var staticConfig = testInjector.resolve("staticConfig");
            assert.isFalse(service.isEnabled(staticConfig.ERROR_REPORT_SETTING_NAME).wait());
            assert.isFalse(service.isEnabled(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME).wait());
        });
    });
    describe("setStatus", function () {
        it("sets correct status", function () {
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            var staticConfig = testInjector.resolve("staticConfig");
            service.setStatus(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME, false).wait();
            assert.isTrue(savedSettingNamesAndValues.indexOf(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME + ".false") !== -1);
        });
        it("calls eqatec stop when all analytics trackings are disabled", function () {
            baseTestScenario.exceptionsTracking = false;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            var staticConfig = testInjector.resolve("staticConfig");
            service.trackFeature(featureName).wait();
            assert.isTrue(trackedFeatureNamesAndValues.indexOf("CLI." + featureName) !== -1);
            service.setStatus(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME, false).wait();
            assert.isTrue(savedSettingNamesAndValues.indexOf(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME + ".false") !== -1);
            assert.isTrue(isEqatecStopCalled);
        });
        it("tracks that user had disabled feature tracking", function () {
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            var staticConfig = testInjector.resolve("staticConfig");
            service.setStatus(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME, false).wait();
            assert.isTrue(savedSettingNamesAndValues.indexOf(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME + ".false") !== -1);
            assert.isTrue(trackedFeatureNamesAndValues.indexOf(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME + ".disabled") !== -1);
        });
        it("tracks that user had enabled feature tracking", function () {
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            var staticConfig = testInjector.resolve("staticConfig");
            service.setStatus(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME, true).wait();
            assert.isTrue(savedSettingNamesAndValues.indexOf(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME + ".true") !== -1);
            assert.isTrue(trackedFeatureNamesAndValues.indexOf(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME + ".enabled") !== -1);
        });
        it("tracks that user had disabled exceptions tracking", function () {
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            var staticConfig = testInjector.resolve("staticConfig");
            service.setStatus(staticConfig.ERROR_REPORT_SETTING_NAME, false).wait();
            assert.isTrue(savedSettingNamesAndValues.indexOf(staticConfig.ERROR_REPORT_SETTING_NAME + ".false") !== -1);
            assert.isTrue(trackedFeatureNamesAndValues.indexOf(staticConfig.ERROR_REPORT_SETTING_NAME + ".disabled") !== -1);
        });
        it("tracks that user had enabled exceptions tracking", function () {
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            var staticConfig = testInjector.resolve("staticConfig");
            service.setStatus(staticConfig.ERROR_REPORT_SETTING_NAME, true).wait();
            assert.isTrue(savedSettingNamesAndValues.indexOf(staticConfig.ERROR_REPORT_SETTING_NAME + ".true") !== -1);
            assert.isTrue(trackedFeatureNamesAndValues.indexOf(staticConfig.ERROR_REPORT_SETTING_NAME + ".enabled") !== -1);
        });
    });
    describe("getStatusMessage", function () {
        it("returns correct string results when status is enabled", function () {
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            var staticConfig = testInjector.resolve("staticConfig");
            var expectedMsg = "Expected result";
            assert.equal(expectedMsg + " is enabled.", service.getStatusMessage(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME, false, expectedMsg).wait());
        });
        it("returns correct string results when status is disabled", function () {
            baseTestScenario.featureTracking = false;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            var staticConfig = testInjector.resolve("staticConfig");
            var expectedMsg = "Expected result";
            assert.equal(expectedMsg + " is disabled.", service.getStatusMessage(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME, false, expectedMsg).wait());
        });
        it("returns correct string results when status is not confirmed", function () {
            baseTestScenario.featureTracking = undefined;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            var staticConfig = testInjector.resolve("staticConfig");
            var expectedMsg = "Expected result";
            assert.equal(expectedMsg + " is disabled until confirmed.", service.getStatusMessage(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME, false, expectedMsg).wait());
        });
        it("returns correct json results when status is enabled", function () {
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            var staticConfig = testInjector.resolve("staticConfig");
            assert.deepEqual(JSON.stringify({ "enabled": true }), service.getStatusMessage(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME, true, "").wait());
        });
        it("returns correct json results when status is disabled", function () {
            baseTestScenario.featureTracking = false;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            var staticConfig = testInjector.resolve("staticConfig");
            assert.deepEqual(JSON.stringify({ "enabled": false }), service.getStatusMessage(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME, true, "").wait());
        });
        it("returns correct json results when status is not confirmed", function () {
            baseTestScenario.featureTracking = undefined;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            var staticConfig = testInjector.resolve("staticConfig");
            assert.deepEqual(JSON.stringify({ "enabled": null }), service.getStatusMessage(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME, true, "").wait());
        });
    });
    describe("checkConsent", function () {
        it("enables feature tracking when user confirms", function () {
            baseTestScenario.featureTracking = undefined;
            baseTestScenario.exceptionsTracking = false;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.checkConsent().wait();
            var staticConfig = testInjector.resolve("staticConfig");
            assert.isTrue(savedSettingNamesAndValues.indexOf(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME + ".true") !== -1);
        });
        it("disables feature tracking user confirms", function () {
            baseTestScenario.featureTracking = undefined;
            baseTestScenario.prompterConfirmResult = false;
            baseTestScenario.exceptionsTracking = false;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.checkConsent().wait();
            var staticConfig = testInjector.resolve("staticConfig");
            assert.isTrue(savedSettingNamesAndValues.indexOf(staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME + ".false") !== -1);
        });
        it("enables exception tracking when it is not set", function () {
            baseTestScenario.featureTracking = false;
            baseTestScenario.exceptionsTracking = undefined;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.checkConsent().wait();
            var staticConfig = testInjector.resolve("staticConfig");
            assert.isTrue(savedSettingNamesAndValues.indexOf(staticConfig.ERROR_REPORT_SETTING_NAME + ".true") !== -1);
        });
        it("do nothing when exception and feature tracking are already set", function () {
            baseTestScenario.featureTracking = baseTestScenario.exceptionsTracking = true;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.checkConsent().wait();
            assert.deepEqual(savedSettingNamesAndValues, "");
        });
        it("do nothing when cannot make request", function () {
            baseTestScenario.canDoRequest = false;
            baseTestScenario.featureTracking = baseTestScenario.exceptionsTracking = undefined;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.checkConsent().wait();
            assert.deepEqual(savedSettingNamesAndValues, "");
        });
        it("sends information that user had accepted feature tracking", function () {
            baseTestScenario.featureTracking = undefined;
            baseTestScenario.exceptionsTracking = false;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.checkConsent().wait();
            var staticConfig = testInjector.resolve("staticConfig");
            assert.isTrue(trackedFeatureNamesAndValues.indexOf("Accept" + staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME + ".true") !== -1);
        });
        it("sends information that user had rejected feature tracking", function () {
            baseTestScenario.featureTracking = undefined;
            baseTestScenario.prompterConfirmResult = false;
            baseTestScenario.exceptionsTracking = false;
            var testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
            service.checkConsent().wait();
            var staticConfig = testInjector.resolve("staticConfig");
            assert.isTrue(trackedFeatureNamesAndValues.indexOf("Accept" + staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME + ".false") !== -1);
        });
    });
    describe("uses correct settings on different os-es", function () {
        var name = "unitTests";
        var testInjector;
        var osType = os.type;
        var osRelease = os.release;
        var release = "1.0";
        beforeEach(function () {
            testInjector = createTestInjector(baseTestScenario);
            service = testInjector.resolve("analyticsService");
        });
        after(function () {
            os.type = osType;
            os.release = osRelease;
        });
        it("sets correct userAgent on Windows", function () {
            os.type = function () { return "Windows_NT"; };
            os.release = function () { return release; };
            service.track(name, featureName).wait();
            assert.equal(lastUsedEqatecSettings.userAgent, "(Windows NT " + release + ")");
        });
        it("sets correct userAgent on MacOS", function () {
            os.type = function () { return "Darwin"; };
            os.release = function () { return release; };
            service.track(name, featureName).wait();
            assert.equal(lastUsedEqatecSettings.userAgent, "(Mac OS X " + release + ")");
        });
        it("sets correct userAgent on other OSs", function () {
            os.type = function () { return "Linux"; };
            os.release = function () { return release; };
            service.track(name, featureName).wait();
            assert.equal(lastUsedEqatecSettings.userAgent, "(Linux)");
        });
    });
});
