(function () {
    /*global JSZip*/
    'use strict';
    describe('Session Service', function () {
        var ufSession, _;
        // since we are testing the session we don't want a default one setup
        testHarness.beforeEachCreateMocks();
        var testStartSessionPromise;
        testHarness.beforeEachInjectSession(function (sessionPromise) {
            testStartSessionPromise = sessionPromise;
        });
        var target = testHarness.target;
        function testDataProvider(done) {
            ufSession.registerSessionDataProvider('sessionTest', {
                onSessionLoad: function (newData) {
                    expect(newData).toBeUndefined();
                    done();
                }
            });
        }
        beforeEach(inject(function (_ufSession_) {
            ufSession = _ufSession_;
        }));
        describe('New', function () {
            it('should call data providers on registeration', function (done) {
                testDataProvider(done);
            });
            it('should provide configured target ccxml file content', function () {
                expect(ufSession.getCCXML()).toBe(target.expectedCCXMLFileContent);
            });
            it('should provide configured target cores list', function () {
                var cores = ufSession.getCores();
                expect(cores.length).toBe(1);
                var core = cores[0];
                expect(core.name).toBe(target.expectedCoreName);
            });
            it('should not start a new session if already started', function () {
                var sessionPromise = ufSession.startIfNeeded(target.deviceID, target.connectionID);
                expect(testStartSessionPromise).toBe(sessionPromise);
            });
            it('should force start a new session', function (done) {
                var sessionPromise = ufSession.startIfNeeded(target.deviceID, target.connectionID, true);
                expect(testStartSessionPromise).not.toBe(sessionPromise);
                testDataProvider(done);
            });
        });
        describe('Save/Load', function () {
            function testSaveSession(done) {
                testHarness.fileDialogs.nextFD(testHarness.fileDialogs.createFD('test_session.uniflash', 'test_session.uniflash'));
                pexpect(ufSession.save(), function () {
                    expect(true).toBe(true);
                }, done);
            }
            it('should save a new session', function (done) {
                testSaveSession(done);
            });
            it('should save core session properties', function (done) {
                testSaveSession(function () {
                    var lastSaved = JSON.parse(testHarness.fileStorage.lastSaveFD().contents);
                    expect(lastSaved.session).toBeDefined();
                    done();
                });
            });
            it('should call registered data provider on save', function (done) {
                var provider = createFakeSessionProvider('sessionTest');
                testSaveSession(function () {
                    var lastSaved = JSON.parse(testHarness.fileStorage.lastSaveFD().contents);
                    var savedFakeSessionData = lastSaved.sessionTest;
                    expect(angular.equals(provider.fakeSessionData, savedFakeSessionData)).toBe(true);
                    expect(provider.getSessionDataCalled).toBe(true);
                    done();
                });
            });
            function createFakeSessionProvider(id) {
                var provider = {};
                provider.fakeSessionData = {};
                provider.fakeSessionData['fake_key' + id] = 'fake_value' + id;
                provider.onSessionLoadCalled = false;
                provider.getSessionDataCalled = false;
                ufSession.registerSessionDataProvider(id, {
                    onSessionLoad: function (newData) {
                        provider.fakeSessionData = newData;
                        provider.onSessionLoadCalled = true;
                    },
                    getSessionData: function () {
                        provider.getSessionDataCalled = true;
                        return provider.fakeSessionData;
                    }
                });
                return provider;
            }
            function createFakeSessionProviders(num) {
                var fakeSessionDataProviders = {};
                // lets create 10 providers
                for (var i = 0; i < num; i++) {
                    var id = 'fake_provider' + i;
                    fakeSessionDataProviders[id] = createFakeSessionProvider(id);
                }
                return fakeSessionDataProviders;
            }
            function verifyFakeSessionProviderData(fakeSessionDataProviders, lastSavedSession) {
                _.each(fakeSessionDataProviders, function (provider, id) {
                    var savedFakeSessionData = lastSavedSession[id];
                    expect(angular.equals(provider.fakeSessionData, savedFakeSessionData)).toBe(true);
                    expect(provider.getSessionDataCalled).toBe(true);
                });
            }
            function testSaveSessionMultipleDataProviders(done, fakeSessionDataProviders) {
                testSaveSession(function () {
                    var lastSavedSession = JSON.parse(testHarness.fileStorage.lastSaveFD().contents);
                    verifyFakeSessionProviderData(fakeSessionDataProviders, lastSavedSession);
                    done();
                });
            }
            it('should call multiple registered data providers on save', function (done) {
                var fakeSessionDataProviders = createFakeSessionProviders(10);
                testSaveSessionMultipleDataProviders(done, fakeSessionDataProviders);
            });
            var sessionLoadTestData = {
                'fake_provider0': {
                    'fake_keyfake_provider0': 'fake_valuefake_provider0'
                },
                'fake_provider1': {
                    'fake_keyfake_provider1': 'fake_valuefake_provider1'
                },
                'session': {
                    'version': 'uniflash_session_format_version_1',
                    'deviceID': 'MSP430FR5969',
                    'connectionID': 'TIMSP430-USB',
                    'cores': [{
                            'id': '0',
                            'name': 'MSP430FR5969'
                        }]
                }
            };
            it('should load a saved session', function (done) {
                // expectLoadData will verify data load
                var providers = createFakeSessionProviders(2);
                var fd = testHarness.fileDialogs.createFD('load_test_session.uniflash', 'load_test_session.uniflash', JSON.stringify(sessionLoadTestData));
                testHarness.fileDialogs.nextFD(fd);
                testHarness.fileStorage.nextOpenFD(fd);
                pexpect(ufSession.load(), function () {
                    _.each(providers, function (provider, id) {
                        var expectLoadData = sessionLoadTestData[id];
                        expect(angular.equals(provider.fakeSessionData, expectLoadData)).toBe(true);
                        expect(provider.onSessionLoadCalled).toBe(true);
                    });
                }, done);
            });
        });
    });
})();
