define([
    'jquery',
    'underscore',
    'js/common_helpers/template_helpers',
    'js/common_helpers/ajax_helpers',
    'js/student_account/models/RegisterModel',
    'js/student_account/views/RegisterView'
], function($, _, TemplateHelpers, AjaxHelpers, RegisterModel, RegisterView) {
    'use strict';

    describe('edx.student.account.RegisterView', function() {

        var model = null,
            view = null,
            requests = null,
            authComplete = false,
            PLATFORM_NAME = 'edX',
            COURSE_ID = "edX/DemoX/Fall",
            USER_DATA = {
                email: 'xsy@edx.org',
                name: 'Xsy M. Education',
                username: 'Xsy',
                password: 'xsyisawesome',
                level_of_education: 'p',
                gender: 'm',
                year_of_birth: 2014,
                mailing_address: '141 Portland',
                goals: 'To boldly learn what no letter of the alphabet has learned before',
                honor_code: true
            },
            THIRD_PARTY_AUTH = {
                currentProvider: null,
                providers: [
                    {
                        name: 'Google',
                        iconClass: 'icon-google-plus',
                        loginUrl: '/auth/login/google-oauth2/?auth_entry=account_login',
                        registerUrl: '/auth/login/google-oauth2/?auth_entry=account_register'
                    },
                    {
                        name: 'Facebook',
                        iconClass: 'icon-facebook',
                        loginUrl: '/auth/login/facebook/?auth_entry=account_login',
                        registerUrl: '/auth/login/facebook/?auth_entry=account_register'
                    }
                ]
            },
            FORM_DESCRIPTION = {
                method: 'post',
                submit_url: '/user_api/v1/account/registration/',
                fields: [
                    {
                        name: 'email',
                        label: 'Email',
                        defaultValue: '',
                        type: 'email',
                        required: true,
                        placeholder: 'place@holder.org',
                        instructions: 'Enter your email.',
                        restrictions: {}
                    },
                    {
                        name: 'name',
                        label: 'Full Name',
                        defaultValue: '',
                        type: 'text',
                        required: true,
                        instructions: 'Enter your username.',
                        restrictions: {}
                    },
                    {
                        name: 'username',
                        label: 'Username',
                        defaultValue: '',
                        type: 'text',
                        required: true,
                        instructions: 'Enter your username.',
                        restrictions: {}
                    },
                    {
                        name: 'password',
                        label: 'Password',
                        defaultValue: '',
                        type: 'password',
                        required: true,
                        instructions: 'Enter your password.',
                        restrictions: {}
                    },
                    {
                        name: 'level_of_education',
                        label: 'Highest Level of Education Completed',
                        defaultValue: '',
                        type: 'select',
                        options: [
                            {value: "", name: "--"},
                            {value: "p", name: "Doctorate"},
                            {value: "m", name: "Master's or professional degree"},
                            {value: "b", name: "Bachelor's degree"},
                        ],
                        required: false,
                        instructions: 'Select your education level.',
                        restrictions: {}
                    },
                    {
                        name: 'gender',
                        label: 'Gender',
                        defaultValue: '',
                        type: 'select',
                        options: [
                            {value: "", name: "--"},
                            {value: "m", name: "Male"},
                            {value: "f", name: "Female"},
                            {value: "o", name: "Other"},
                        ],
                        required: false,
                        instructions: 'Select your gender.',
                        restrictions: {}
                    },
                    {
                        name: 'year_of_birth',
                        label: 'Year of Birth',
                        defaultValue: '',
                        type: 'select',
                        options: [
                            {value: "", name: "--"},
                            {value: 1900, name: "1900"},
                            {value: 1950, name: "1950"},
                            {value: 2014, name: "2014"},
                        ],
                        required: false,
                        instructions: 'Select your year of birth.',
                        restrictions: {}
                    },
                    {
                        name: 'mailing_address',
                        label: 'Mailing Address',
                        defaultValue: '',
                        type: 'textarea',
                        required: false,
                        instructions: 'Enter your mailing address.',
                        restrictions: {}
                    },
                    {
                        name: 'goals',
                        label: 'Goals',
                        defaultValue: '',
                        type: 'textarea',
                        required: false,
                        instructions: "If you'd like, tell us why you're interested in edX.",
                        restrictions: {}
                    },
                    {
                        name: 'honor_code',
                        label: 'I agree to the <a href="/honor">Terms of Service and Honor Code</a>',
                        defaultValue: '',
                        type: 'checkbox',
                        required: true,
                        instructions: '',
                        restrictions: {}
                    }
                ]
            };

        var createRegisterView = function(that) {
            // Initialize the register model
            model = new RegisterModel({}, {
                url: FORM_DESCRIPTION.submit_url,
                method: FORM_DESCRIPTION.method
            });

            // Initialize the register view
            view = new RegisterView({
                fields: FORM_DESCRIPTION.fields,
                model: model,
                thirdPartyAuth: THIRD_PARTY_AUTH,
                platformName: PLATFORM_NAME
            });

            // Spy on AJAX requests
            requests = AjaxHelpers.requests(that);

            // Intercept events from the view
            authComplete = false;
            view.on("auth-complete", function() {
                authComplete = true;
            });
        };

        var submitForm = function(validationSuccess) {
            // Simulate manual entry of registration form data
            $('#register-email').val(USER_DATA.email);
            $('#register-name').val(USER_DATA.name);
            $('#register-username').val(USER_DATA.username);
            $('#register-password').val(USER_DATA.password);
            $('#register-level_of_education').val(USER_DATA.level_of_education);
            $('#register-gender').val(USER_DATA.gender);
            $('#register-year_of_birth').val(USER_DATA.year_of_birth);
            $('#register-mailing_address').val(USER_DATA.mailing_address);
            $('#register-goals').val(USER_DATA.goals);

            // Check the honor code checkbox
            $('#register-honor_code').prop('checked', USER_DATA.honor_code);

            // Create a fake click event
            var clickEvent = $.Event('click');

            // If validationSuccess isn't passed, we avoid
            // spying on `view.validate` twice
            if ( !_.isUndefined(validationSuccess) ) {
                // Force validation to return as expected
                spyOn(view, 'validate').andReturn({
                    isValid: validationSuccess,
                    message: 'Submission was validated.'
                });
            }

            // Submit the email address
            view.submitForm(clickEvent);
        };

        beforeEach(function() {
            setFixtures('<div id="register-form"></div>');
            TemplateHelpers.installTemplate('templates/student_account/register');
            TemplateHelpers.installTemplate('templates/student_account/form_field');
        });

        it('registers a new user', function() {
            createRegisterView(this);

            // Submit the form, with successful validation
            submitForm( true );

            // Verify that the client contacts the server with the expected data
            AjaxHelpers.expectRequest(
                requests, 'POST',
                FORM_DESCRIPTION.submit_url,
                $.param( USER_DATA )
            );

            // Respond with status code 200
            AjaxHelpers.respondWithJson(requests, {});

            // Verify that auth complete is triggered
            expect(authComplete).toBe(true);
            // Form button should be disabled on success.
            expect(view.$submitButton).toHaveAttr('disabled');
        });

        it('sends analytics info containing the enrolled course ID', function() {
            createRegisterView( this );

            // Simulate that the user is attempting to enroll in a course
            // by setting the course_id query string param.
            spyOn($, 'url').andCallFake(function( param ) {
                if (param === "?course_id") {
                    return encodeURIComponent( COURSE_ID );
                }
            });

            // Attempt to register
            submitForm( true );

            // Verify that the client sent the course ID for analytics
            var expectedData = {};
            $.extend(expectedData, USER_DATA, {
                analytics: JSON.stringify({
                    enroll_course_id: COURSE_ID
                })
            });

            AjaxHelpers.expectRequest(
                requests, 'POST',
                FORM_DESCRIPTION.submit_url,
                $.param( expectedData )
            );
        });

        it('displays third-party auth registration buttons', function() {
            createRegisterView(this);

            // Verify that Google and Facebook registration buttons are displayed
            expect($('.button-Google')).toBeVisible();
            expect($('.button-Facebook')).toBeVisible();
        });

        it('validates registration form fields', function() {
            createRegisterView(this);

            // Submit the form, with successful validation
            submitForm(true);

            // Verify that validation of form fields occurred
            expect(view.validate).toHaveBeenCalledWith($('#register-email')[0]);
            expect(view.validate).toHaveBeenCalledWith($('#register-name')[0]);
            expect(view.validate).toHaveBeenCalledWith($('#register-username')[0]);
            expect(view.validate).toHaveBeenCalledWith($('#register-password')[0]);

            // Verify that no submission errors are visible
            expect(view.$errors).toHaveClass('hidden');
            // Form button should be disabled on success.
            expect(view.$submitButton).toHaveAttr('disabled');
        });

        it('displays registration form validation errors', function() {
            createRegisterView(this);

            // Submit the form, with failed validation
            submitForm(false);

            // Verify that submission errors are visible
            expect(view.$errors).not.toHaveClass('hidden');

            // Expect that auth complete is NOT triggered
            expect(authComplete).toBe(false);
            // Form button should be re-enabled on error.
            expect(view.$submitButton).not.toHaveAttr('disabled');
        });

        it('displays an error if the server returns an error while registering', function() {
            createRegisterView(this);

            // Submit the form, with successful validation
            submitForm(true);

            // Simulate an error from the LMS servers
            AjaxHelpers.respondWithError(requests);

            // Expect that an error is displayed and that auth complete is NOT triggered
            expect(view.$errors).not.toHaveClass('hidden');
            expect(authComplete).toBe(false);

            // If we try again and succeed, the error should go away
            submitForm();

            // This time, respond with status code 200
            AjaxHelpers.respondWithJson(requests, {});

            // Expect that the error is hidden and that auth complete is triggered
            expect(view.$errors).toHaveClass('hidden');
            expect(authComplete).toBe(true);
            // Form button should be disabled on success.
            expect(view.$submitButton).toHaveAttr('disabled');
        });
    });
});
