define([
    'backbone',
    'jquery',
    'js/programs/views/program_creator_view'
],
    function(Backbone, $, ProgramCreatorView) {
        'use strict';

        describe('ProgramCreatorView', function() {
            var view = {},
                Router = Backbone.Router.extend({
                    initialize: function(options) {
                        this.homeUrl = options.homeUrl;
                    },
                    goHome: function() {
                        window.location.href = this.homeUrl;
                    }
                }),
                organizations = {
                    count: 1,
                    previous: null,
                    'num_pages': 1,
                    results: [{
                        'display_name': 'test-org-display_name',
                        'key': 'test-org-key'
                    }],
                    next: null
                },
                sampleInput,
                completeForm = function(data) {
                    view.$el.find('#program-name').val(data.name);
                    view.$el.find('#program-subtitle').val(data.subtitle);
                    view.$el.find('#program-org').val(data.organizations);

                    if (data.category) {
                        view.$el.find('#program-type').val(data.category);
                    }

                    if (data.marketing_slug) {
                        view.$el.find('#program-marketing-slug').val(data.marketing_slug);
                    }
                },
                verifyValidation = function(data, invalidAttr) {
                    var errorClass = 'has-error',
                        $invalidElement = view.$el.find('[name="' + invalidAttr + '"]'),
                        $errorMsg = $invalidElement.siblings('.field-message'),
                        inputErrorMsg = '';

                    completeForm(data);

                    view.$el.find('.js-create-program').click();
                    inputErrorMsg = $invalidElement.data('error');

                    expect(view.model.save).not.toHaveBeenCalled();
                    expect($invalidElement).toHaveClass(errorClass);
                    expect($errorMsg).toHaveClass(errorClass);
                    expect(inputErrorMsg).toBeDefined();
                    expect($errorMsg.find('.field-message-content').html()).toEqual(inputErrorMsg);
                };

            var validateFormSubmitted = function(view, programId) {
                expect($.ajax).toHaveBeenCalled();
                expect(view.saveSuccess).toHaveBeenCalled();
                expect(view.goToView).toHaveBeenCalledWith(String(programId));
                expect(view.saveError).not.toHaveBeenCalled();
            };

            beforeEach(function() {
                // Set the DOM
                setFixtures('<div class="js-program-admin"></div>');

                jasmine.clock().install();

                spyOn(ProgramCreatorView.prototype, 'saveSuccess').and.callThrough();
                spyOn(ProgramCreatorView.prototype, 'goToView').and.callThrough();
                spyOn(ProgramCreatorView.prototype, 'saveError').and.callThrough();
                spyOn(Router.prototype, 'goHome');

                sampleInput = {
                    category: 'XSeries',
                    organizations: 'test-org-key',
                    name: 'Test Course Name',
                    subtitle: 'Test Course Subtitle',
                    marketing_slug: 'test-management'
                };

                view = new ProgramCreatorView({
                    router: new Router({
                        homeUrl: '/author/home'
                    })
                });

                view.organizations.set(organizations);
                view.render();
            });

            afterEach(function() {
                view.destroy();

                jasmine.clock().uninstall();
            });

            it('should exist', function() {
                expect(view).toBeDefined();
            });

            it('should get the form data', function() {
                var formData = {};

                completeForm(sampleInput);
                formData = view.getData();

                expect(formData.name).toEqual(sampleInput.name);
                expect(formData.subtitle).toEqual(sampleInput.subtitle);
                expect(formData.organizations[0].key).toEqual(sampleInput.organizations);
            });

            it('should submit the form when the user clicks submit', function() {
                var programId = 123;

                completeForm(sampleInput);

                spyOn($, 'ajax').and.callFake(function(event) {
                    event.success({id: programId});
                });

                view.$el.find('.js-create-program').click();

                validateFormSubmitted(view, programId);
            });

            it('should submit the form correctly when creating micromasters program ', function() {
                var programId = 221;
                sampleInput.category = 'MicroMasters';

                completeForm(sampleInput);

                spyOn($, 'ajax').and.callFake(function(event) {
                    event.success({id: programId});
                });

                view.$el.find('.js-create-program').click();

                validateFormSubmitted(view, programId);
            });

            it('should run the saveError when model save failures occur', function() {
                spyOn($, 'ajax').and.callFake(function(event) {
                    event.error();
                });

                // Fill out the form with valid data so that form model validation doesn't
                // prevent the model from being saved.
                completeForm(sampleInput);
                view.$el.find('.js-create-program').click();

                expect($.ajax).toHaveBeenCalled();
                expect(view.saveSuccess).not.toHaveBeenCalled();
                expect(view.saveError).toHaveBeenCalled();
            });

            it('should set the model when valid form data is submitted', function() {
                completeForm(sampleInput);

                spyOn($, 'ajax').and.callFake(function(event) {
                    event.success({id: 10001110101});
                });

                view.$el.find('.js-create-program').click();

                expect(view.model.get('name')).toEqual(sampleInput.name);
                expect(view.model.get('subtitle')).toEqual(sampleInput.subtitle);
                expect(view.model.get('organizations')[0].key).toEqual(sampleInput.organizations);
                expect(view.model.get('marketing_slug')).toEqual(sampleInput.marketing_slug);
            });

            it('should not set the model when bad program type selected', function() {
                var invalidInput = $.extend({}, sampleInput);
                spyOn(view.model, 'save');

                // No name provided.
                invalidInput.category = '';
                verifyValidation(invalidInput, 'category');

                // bad program type name
                invalidInput.name = 'badprogramtype';
                verifyValidation(invalidInput, 'category');
            });

            it('should not set the model when an invalid program name is submitted', function() {
                var invalidInput = $.extend({}, sampleInput);

                spyOn(view.model, 'save');

                // No name provided.
                invalidInput.name = '';
                verifyValidation(invalidInput, 'name');

                // Name is too long.
                invalidInput.name = 'x'.repeat(256);
                verifyValidation(invalidInput, 'name');
            });

            it('should not set the model when an invalid program subtitle is submitted', function() {
                var invalidInput = $.extend({}, sampleInput);

                spyOn(view.model, 'save');

                // Subtitle is too long.
                invalidInput.subtitle = 'x'.repeat(300);
                verifyValidation(invalidInput, 'subtitle');
            });

            it('should not set the model when an invalid category is submitted', function() {
                var invalidInput = $.extend({}, sampleInput);

                spyOn(view.model, 'save');

                // Category other than 'xseries' selected.
                invalidInput.category = 'yseries';
                verifyValidation(invalidInput, 'category');
            });

            it('should not set the model when an invalid organization key is submitted', function() {
                var invalidInput = $.extend({}, sampleInput);

                spyOn(view.model, 'save');

                // No organization selected.
                invalidInput.organizations = 'false';
                verifyValidation(invalidInput, 'organizations');
            });

            it('should not set the model when an invalid marketing slug is submitted', function() {
                var invalidInput = $.extend({}, sampleInput);

                spyOn(view.model, 'save');

                // Marketing slug is too long.
                invalidInput.marketing_slug = 'x'.repeat(256);
                verifyValidation(invalidInput, 'marketing_slug');
            });

            it('should abort the view when the cancel button is clicked', function() {
                completeForm(sampleInput);
                expect(view.$parentEl.html().length).toBeGreaterThan(0);
                view.$el.find('.js-abort-view').click();
                expect(view.router.goHome).toHaveBeenCalled();
            });
        });
    }
);
