define([
    'Squire',
    'test-helper',
    'bitbucket/internal/util/events'
], function(
    Squire,
    testHelper,
    events
) {

    'use strict';

    module('diff-view-options');

    var injector = new Squire();
    injector.mock('bitbucket/internal/model/page-state', testHelper.mockPageState());
    injector.mock('bitbucket/internal/util/events', events);
    injector.setDefaultDeps(['bitbucket/internal/feature/file-content/diff-view-options']);

    // async setup
    function setup(diffViewOptions) {
        diffViewOptions.set('test-option', 'test-value');
        diffViewOptions.set('test-option2', 'test-value2');
        diffViewOptions.set('test-option3', 'test-value3');
    }

    function teardown(diffViewOptions) {
        events.off('bitbucket.internal.feature.fileContent.optionsChanged', eventHandlerTest);
        diffViewOptions.set('test-option', null);
    }

    function eventHandlerTest() {
        ok(true, 'bitbucket.internal.feature.fileContent.optionsChanged triggered');
    }

    injector.test('Correct diff option is stored', function (assert, diffViewOptions) {
        setup(diffViewOptions);
        assert.expect(3);

        assert.equal(diffViewOptions.get('test-option'), 'test-value', 'Option matches');
        assert.equal(diffViewOptions.get('some-undefined-option'), undefined, 'Undefined option not defined');

        events.on('bitbucket.internal.feature.fileContent.optionsChanged', eventHandlerTest);

        diffViewOptions.set('test-option', 'testing-event-handler');
        teardown(diffViewOptions);
    });

    injector.test('proxy', function(assert, diffViewOptions) {
        setup(diffViewOptions);
        var proxy = diffViewOptions.proxy({
            'test-option' : 'sentinal',
            'test-option2' : undefined
        });

        assert.equal(diffViewOptions.get('test-option'), 'test-value', 'Original options not changed.');
        assert.equal(diffViewOptions.get('test-option2'), 'test-value2', 'Original options not changed.');
        assert.equal(diffViewOptions.get('test-option3'), 'test-value3', 'Original options not changed.');

        assert.equal(proxy.get('test-option'), 'sentinal', 'Proxy uses override value.');
        assert.equal(proxy.get('test-option2'), 'test-value2', 'Proxy passes through undefined.');
        assert.equal(proxy.get('test-option3'), 'test-value3', 'Proxy passes through unspecified values.');

        var proxyChange = sinon.spy();
        var rootChange = sinon.spy();
        var globalChange = sinon.spy();

        proxy.on('change', proxyChange);
        diffViewOptions.on('change', rootChange);
        events.on('bitbucket.internal.feature.fileContent.optionsChanged', globalChange);

        try {
            proxy.set('test-option', 'new-value');

            assert.ok(!proxyChange.called, 'no event for ignored set');
            assert.ok(!rootChange.called, 'no event for ignored set');
            assert.ok(!globalChange.called, 'no event for ignored set');

            proxy.set('test-option2', 'new-value2');
            proxy.set('test-option3', 'new-value3');

            assert.ok(proxyChange.calledTwice, 'Fires events for undefined/unspecified options');
            assert.ok(rootChange.calledTwice, 'Fires events for undefined/unspecified options');
            assert.ok(globalChange.calledTwice, 'Fires events for undefined/unspecified options');

            assert.equal(proxy.get('test-option'), 'sentinal', 'Proxy ignores set value for overrides.');
            assert.equal(proxy.get('test-option2'), 'new-value2', 'Proxy accepts undefined options.');
            assert.equal(proxy.get('test-option3'), 'new-value3', 'Proxy accepts unspecified options.');
        } finally {
            proxy.off('change', proxyChange);
            diffViewOptions.off('change', rootChange);
            events.off('bitbucket.internal.feature.fileContent.optionsChanged', globalChange);
        }
        teardown(diffViewOptions);
    });


});
