define(
    [
        "jquery", "underscore",
        "js/views/video/transcripts/utils", "js/views/video/transcripts/message_manager",
        "js/views/video/transcripts/file_uploader", "sinon",
        "xmodule"
    ],
function ($, _, Utils, MessageManager, FileUploader, sinon) {
    'use strict';

    describe('Transcripts.MessageManager', function () {
        var videoListEntryTemplate = readFixtures(
                'video/transcripts/metadata-videolist-entry.underscore'
            ),
            foundTemplate = readFixtures(
                'video/transcripts/messages/transcripts-found.underscore'
            ),
            handlers = {
                importHandler: ['replace', 'Error: Import failed.'],
                replaceHandler: ['replace', 'Error: Replacing failed.'],
                chooseHandler: ['choose', 'Error: Choosing failed.', 'video_id']
            },
            view, fileUploader, sinonXhr;

        beforeEach(function () {
            var videoList, $container;

            fileUploader = FileUploader.prototype;

            setFixtures(
                $("<div>", {id: "metadata-videolist-entry"})
                    .html(videoListEntryTemplate)
            );
            appendSetFixtures(
                $("<script>",
                    {
                        id: "transcripts-found",
                        type: "text/template"
                    }
                ).text(foundTemplate)
            );

            videoList = jasmine.createSpyObj(
                'MetadataView.VideoList',
                ['getVideoObjectsList']
            );
            $container = $('#metadata-videolist-entry');

            spyOn(fileUploader, 'initialize').and.callThrough();
            spyOn(console, 'error');
            spyOn(Utils.Storage, 'set');

            view = new MessageManager({
                el: $container,
                parent: videoList,
                component_locator: 'component_locator'
            });
        });

        it('Initialize', function () {
            expect(fileUploader.initialize).toHaveBeenCalledWith({
                el: view.$el,
                messenger: view,
                component_locator: view.component_locator,
                videoListObject: view.options.parent
            });
        });

        describe('Render', function () {

            beforeEach(function () {
                spyOn(_,'template').and.callThrough();
                spyOn(view.fileUploader, 'render');
            });

            it('Template doesn\'t exist', function () {
                view.render('incorrect_template_name');

                expect(console.error).toHaveBeenCalled();
                expect(_.template).not.toHaveBeenCalled();
                expect(view.$el.find('.transcripts-status'))
                    .toHaveClass('is-invisible');
                expect(view.fileUploader.render).not.toHaveBeenCalled();
            });

            it('All works okay if correct data is passed', function () {
                view.render('found');

                expect(console.error).not.toHaveBeenCalled();
                expect(_.template).toHaveBeenCalled();
                expect(view.$el).not.toHaveClass('is-invisible');
                expect(view.fileUploader.render).toHaveBeenCalled();
            });
        });

        describe('showError', function () {
            var errorMessage ='error',
                $error, $buttons;

            beforeEach(function () {
                view.render('found');
                spyOn(view, 'hideError');
                spyOn($.fn, 'html').and.callThrough();
                $error = view.$el.find('.transcripts-error-message');
                $buttons = view.$el.find('.wrapper-transcripts-buttons');
            });

            it('Error message is not passed', function () {
                view.showError(null);

                expect(view.hideError).not.toHaveBeenCalled();
                expect($error.html).not.toHaveBeenCalled();
                expect($error).toHaveClass('is-invisible');
                expect($buttons).not.toHaveClass('is-invisible');
            });

            it('Show message and buttons', function () {
                view.showError(errorMessage);

                expect(view.hideError).toHaveBeenCalled();
                expect($error.html).toHaveBeenCalled();
                expect($error).not.toHaveClass('is-invisible');
                expect($buttons).not.toHaveClass('is-invisible');
            });

            it('Show message and hide buttons', function () {
                view.showError(errorMessage, true);

                expect(view.hideError).toHaveBeenCalled();
                expect($error.html).toHaveBeenCalled();
                expect($error).not.toHaveClass('is-invisible');
                expect($buttons).toHaveClass('is-invisible');
            });
        });

        it('hideError', function () {
            view.render('found');

            var $error = view.$el.find('.transcripts-error-message'),
                $buttons = view.$el.find('.wrapper-transcripts-buttons');

            expect($error).toHaveClass('is-invisible');
            expect($buttons).not.toHaveClass('is-invisible');
        });

        $.each(handlers, function(key, value) {
             it(key, function () {
                var eventObj = jasmine.createSpyObj('event', ['preventDefault']);
                spyOn($.fn, 'data').and.returnValue('video_id');
                spyOn(view, 'processCommand');
                view[key](eventObj);
                expect(view.processCommand.calls.mostRecent().args).toEqual(value);
             });
        });

        describe('processCommand', function () {
            var action = 'replace',
                errorMessage = 'errorMessage',
                videoList = void(0),
                extraParamas = 'video_id';

            beforeEach(function () {
                view.render('found');
                spyOn(Utils, 'command').and.callThrough();
                spyOn(view, 'render');
                spyOn(view, 'showError');

                sinonXhr =  sinon.fakeServer.create();
                sinonXhr.autoRespond = true;
            });

            afterEach(function () {
                sinonXhr.restore();
            });

            var assertCommand = function (config) {
                var defaults = {
                        action: 'replace',
                        errorMessage: 'errorMessage',
                        extraParamas: void(0)
                    };
                var args = $.extend({}, defaults, config);

                return view
                    .processCommand(args.action, args.errorMessage, args.extraParamas);
            };

            it('Invoke without extraParamas', function (done) {
                sinonXhr.respondWith([
                    200,
                    { "Content-Type": "application/json"},
                    JSON.stringify({
                      status: 'Success',
                      subs: 'video_id'
                    })
                ]);

                assertCommand({})
                    .then(function () {
                        expect(Utils.command).toHaveBeenCalledWith(
                            action,
                            view.component_locator,
                            videoList,
                            void(0)
                        );
                        expect(view.showError).not.toHaveBeenCalled();
                        expect(view.render.calls.mostRecent().args[0])
                            .toEqual('found');
                        expect(Utils.Storage.set).toHaveBeenCalled();
                    })
                    .always(done);
            });

            it('Invoke with extraParamas', function (done) {
                sinonXhr.respondWith([
                    200,
                    { "Content-Type": "application/json"},
                    JSON.stringify({
                      status: 'Success',
                      subs: 'video_id'
                    })
                ]);

                view.processCommand(action, errorMessage, extraParamas);

                assertCommand({extraParamas : extraParamas})
                    .then(function () {
                        expect(Utils.command).toHaveBeenCalledWith(
                            action,
                            view.component_locator,
                            videoList,
                            {
                                html5_id: extraParamas
                            }
                        );
                        expect(view.showError).not.toHaveBeenCalled();
                        expect(view.render.calls.mostRecent().args[0]).toEqual('found');
                        expect(Utils.Storage.set).toHaveBeenCalled();
                    })
                    .always(done);
            });

            it('Fail', function (done) {
                sinonXhr.respondWith([400, {}, '']);
                assertCommand({})
                    .then(function () {
                        expect(Utils.command).toHaveBeenCalledWith(
                            action,
                            view.component_locator,
                            videoList,
                            void(0)
                        );
                        expect(view.showError).toHaveBeenCalled();
                        expect(view.render).not.toHaveBeenCalled();
                        expect(Utils.Storage.set).not.toHaveBeenCalled();
                    })
                    .always(done);
            });
        });

    });
});
