(function(define) {
    'use strict';
    define([
        'jquery',
        'underscore',
        'sinon',
        'common/js/spec_helpers/template_helpers',
        'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers',
        'js/student_account/models/LoginModel',
        'js/student_account/views/LoginView',
        'js/student_account/models/PasswordResetModel'
    ],
        function($, _, sinon, TemplateHelpers, AjaxHelpers, LoginModel, LoginView, PasswordResetModel) {
            describe('edx.student.account.LoginView', function() {
                var model = null,
                    resetModel = null,
                    view = null,
                    requests = null,
                    authComplete = false,
                    PLATFORM_NAME = 'edX',
                    USER_DATA = {
                        email: 'xsy@edx.org',
                        password: 'xsyisawesome',
                        remember: true
                    },
                    THIRD_PARTY_AUTH = {
                        currentProvider: null,
                        providers: [
                            {
                                id: 'oa2-google-oauth2',
                                name: 'Google',
                                iconClass: 'fa-google-plus',
                                loginUrl: '/auth/login/google-oauth2/?auth_entry=account_login',
                                registerUrl: '/auth/login/google-oauth2/?auth_entry=account_register'
                            },
                            {
                                id: 'oa2-facebook',
                                name: 'Facebook',
                                iconClass: 'fa-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/login_session/',
                        fields: [
                            {
                                placeholder: 'username@domain.com',
                                name: 'email',
                                label: 'Email',
                                defaultValue: '',
                                type: 'email',
                                required: true,
                                instructions: 'Enter your email.',
                                restrictions: {}
                            },
                            {
                                placeholder: '',
                                name: 'password',
                                label: 'Password',
                                defaultValue: '',
                                type: 'password',
                                required: true,
                                instructions: 'Enter your password.',
                                restrictions: {}
                            },
                            {
                                placeholder: '',
                                name: 'remember',
                                label: 'Remember me',
                                defaultValue: '',
                                type: 'checkbox',
                                required: true,
                                instructions: 'Agree to the terms of service.',
                                restrictions: {}
                            }
                        ]
                    },
                    COURSE_ID = 'edX/demoX/Fall';

                var createLoginView = function(test) {
                // Initialize the login model
                    model = new LoginModel({}, {
                        url: FORM_DESCRIPTION.submit_url,
                        method: FORM_DESCRIPTION.method
                    });

                // Initialize the passwordReset model
                    resetModel = new PasswordResetModel({}, {
                        method: 'GET',
                        url: '#'
                    });

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

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

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

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

                // Simulate manual entry of login form data
                    $('#login-email').val(USER_DATA.email);
                    $('#login-password').val(USER_DATA.password);

                // Check the 'Remember me' checkbox
                    $('#login-remember').prop('checked', USER_DATA.remember);

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

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

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

                it('logs the user in', function() {
                    createLoginView(this);

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

                // Form button should be disabled on success.
                    expect(view.$submitButton).toHaveAttr('disabled');

                // 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);
                });

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

                    createLoginView(this);

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

                // Attempt to login
                    submitForm(true);

                // Verify that the client sent the course ID for analytics
                    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 login buttons', function() {
                    createLoginView(this);

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

                it('displays a link to the password reset form', function() {
                    createLoginView(this);

                // Verify that the password reset link is displayed
                    expect($('.forgot-password')).toBeVisible();
                });

                it('validates login form fields', function() {
                    createLoginView(this);

                    submitForm(true);

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

                it('displays login form validation errors', function() {
                    createLoginView(this);

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

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

                // Expect auth complete NOT to have been triggered
                    expect(authComplete).toBe(false);
                // Form button should be re-enabled when errors occur
                    expect(view.$submitButton).not.toHaveAttr('disabled');
                });

                it('displays an error if the server returns an error while logging in', function() {
                    createLoginView(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);
                // Form button should be re-enabled on server failure.
                    expect(view.$submitButton).not.toHaveAttr('disabled');

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

                // Form button should be disabled on success.
                    expect(view.$submitButton).toHaveAttr('disabled');

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

                // Expect that the error is hidden and auth complete is triggered
                    expect(view.$errors).toHaveClass('hidden');
                    expect(authComplete).toBe(true);
                });

                it('displays an error if there is no internet connection', function() {
                    var clock,
                        oldTimeout,
                        timeout;

                // We're defining "no internet connection" in this case as the
                // request timing out.  We use a combination of the sinon fake
                // timer and jQuery.ajaxSetup() to force a request timeout.
                    clock = sinon.useFakeTimers();
                    oldTimeout = $.ajaxSetup().timeout;
                    timeout = 1;
                    $.ajaxSetup({timeout: timeout});

                    createLoginView(this);

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

                // Simulate a request timeout
                    clock.tick(timeout + 1);

                // Expect that an error is displayed and that auth complete is not triggered
                    expect(view.$errors).not.toHaveClass('hidden');
                    expect(authComplete).toBe(false);
                    expect(view.$errors.text()).toContain(
                    'An error has occurred. Check your Internet connection and try again.'
                );

                // Finally, restore the old timeout and turn off the fake timer.
                    $.ajaxSetup({timeout: oldTimeout});
                    clock.restore();
                });

                it('displays an error if there is a server error', function() {
                    createLoginView(this);

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

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

                // Expect that an error is displayed and that auth complete is not triggered
                    expect(view.$errors).not.toHaveClass('hidden');
                    expect(authComplete).toBe(false);
                    expect(view.$errors.text()).toContain(
                    'An error has occurred. Try refreshing the page, or check your Internet connection.'
                );
                });
            });
        });
}).call(this, define || RequireJS.define);
