describe('nclProjects component: ', function () {
    var $componentController;
    var $q;
    var $rootScope;
    var $state;
    var ngDialog;
    var ExportService;
    var ProjectsService;
    var ctrl;
    var projects;
    var sortOptions;

    beforeEach(function () {
        module('nuclio.app');

        inject(function (_$componentController_, _$q_, _$rootScope_, _$state_, _ngDialog_, _ExportService_,
                         _ProjectsService_) {
            $componentController = _$componentController_;
            $q = _$q_;
            $rootScope = _$rootScope_;
            $state = _$state_;
            ngDialog = _ngDialog_;
            ExportService = _ExportService_;
            ProjectsService = _ProjectsService_;

            projects = [
                {
                    metadata: {
                        name: 'my-project-1',
                        namespace: 'nuclio'
                    },
                    spec: {
                        description: 'Some description'
                    },
                    ui: {
                        functions: [],
                        checked: false,
                        delete: angular.noop
                    }
                },
                {
                    metadata: {
                        name: 'my-project-2',
                        namespace: 'nuclio'
                    },
                    spec: {
                        description: 'Some description'
                    },
                    ui: {
                        functions: [],
                        checked: false,
                        delete: angular.noop
                    }
                }
            ];
            sortOptions = [
                {
                    label: 'Name',
                    value: 'metadata.name',
                    active: true
                },
                {
                    label: 'Description',
                    value: 'spec.description',
                    active: false
                }
            ];

            var bindings = {
                projects: projects,
                getProject: $q.when.bind($q),
                getProjects: $q.when.bind($q),
                getFunctions: $q.when.bind($q)
            };
            var element = angular.element('<ncl-projects></ncl-projects>');
            var ImportService = {
                importFile: angular.noop
            };

            ctrl = $componentController('nclProjects', {$element: element, ImportService: ImportService}, bindings);
            ctrl.$onInit();
            $rootScope.$digest();
        });
    });

    afterEach(function () {
        $componentController = null;
        $q = null;
        $rootScope = null;
        $state = null;
        ngDialog = null;
        ExportService = null;
        ProjectsService = null;
        ctrl = null;
        projects = null;
        sortOptions = null;
    });

    describe('$onInit(): ', function () {
        it('should initialize projects array', function () {
            expect(ctrl.projects).toEqual(projects);
        });

        it('should initialize sort options', function () {
            expect(ctrl.sortOptions).not.toBe([]);
        });

        it('should call onFireAction() method if `action-panel_fire-action` broadcast was sent', function () {
            spyOn(ctrl, 'handleProjectAction');

            var data = {
                action: {
                    label: 'EDIT',
                    id: 'edit',
                    icon: 'igz-icon-properties',
                    active: true
                }
            };
            ctrl.projects[0].ui = {
                checked: true
            };
            projects[0].ui = ctrl.projects[0].ui;

            $rootScope.$broadcast('action-panel_fire-action', data);

            $rootScope.$digest();

            expect(ctrl.handleProjectAction).toHaveBeenCalledWith(data.action, [projects[0]]);
        });
    });

    describe('handleProjectAction(): ', function () {
        it('should call action\'s handlers for all checked projects', function () {
            var mockedValue = {
                then: function () {
                    return {
                        'catch': angular.noop
                    }
                }
            };
            ctrl.projects[1].ui.checked = true;
            projects[1].ui = ctrl.projects[1].ui;

            spyOn(ctrl.projects[0].ui, 'delete').and.returnValue(mockedValue);
            spyOn(ctrl.projects[1].ui, 'delete').and.returnValue(mockedValue);

            ctrl.handleProjectAction('delete', [ctrl.projects[0], ctrl.projects[1]]);

            expect(ctrl.projects[0].ui.delete).toHaveBeenCalled();
            expect(ctrl.projects[1].ui.delete).toHaveBeenCalled();
        });
    });

    describe('isProjectsListEmpty(): ', function () {
        it('should return true if projects list in empty', function () {
            ctrl.projects = [];

            expect(ctrl.isProjectsListEmpty()).toBeTruthy();
        });

        it('should return false if projects list in not empty', function () {
            ctrl.projects = projects;

            expect(ctrl.isProjectsListEmpty()).toBeFalsy();
        });
    });

    describe('onApplyFilters(): ', function () {
        it('should call `search-input_refresh-search` broadcast', function () {
            spyOn($rootScope, '$broadcast').and.callThrough();

            ctrl.onApplyFilters();

            expect($rootScope.$broadcast).toHaveBeenCalledWith('search-input_refresh-search');
        });
    });

    describe('onResetFilters(): ', function () {
        it('should call `search-input_reset` broadcast', function () {
            spyOn($rootScope, '$broadcast').and.callThrough();
            ctrl.filtersCounter = 1;

            ctrl.onResetFilters();

            expect($rootScope.$broadcast).toHaveBeenCalledWith('search-input_reset');
            expect(ctrl.filtersCounter).toEqual(0)
        });
    });

    describe('onSelectDropdownAction(): ', function () {
        it('should call `onSelectDropdown` function', function () {
            spyOn(ctrl, 'onSelectDropdownAction');

            ctrl.onSelectDropdownAction({id: 'exportProjects'});

            expect(ctrl.onSelectDropdownAction).toHaveBeenCalled();
        });

        it('should call `exportProject` handler', function () {
            spyOn(ExportService, 'exportProjects');

            ctrl.onSelectDropdownAction({id: 'exportProjects'});

            expect(ExportService.exportProjects).toHaveBeenCalledWith(jasmine.arrayContaining([jasmine.objectContaining({
                metadata: jasmine.objectContaining({
                    name: jasmine.any(String)
                })
            })]), jasmine.any(Function));
        });
    });

    describe('onSortOptionsChange(): ', function () {
        it('should set `sortedColumnName` and `isReverseSorting` according to selected option, and sort projects', function () {
            var option = {
                value: 'metadata.name',
                desc: true
            };
            ctrl.projects = ctrl.sortedProjects = [
                {
                    metadata: {
                        name: 'name1'
                    }
                },
                {
                    metadata: {
                        name: 'name2'
                    }
                }
            ];

            ctrl.onSortOptionsChange(option);

            expect(ctrl.sortedColumnName).toEqual('metadata.name');
            expect(ctrl.isReverseSorting).toEqual(true);
            expect(ctrl.sortedProjects).toEqual([
                {
                    metadata: {
                        name: 'name2'
                    }
                },
                {
                    metadata: {
                        name: 'name1'
                    }
                }
            ]);
        });
    });

    describe('onUpdateFiltersCounter(): ', function () {
        it('should set `filterCounter` to 0 if `filterQuery` is empty', function () {
            ctrl.onUpdateFiltersCounter();

            expect(ctrl.filtersCounter).toEqual(0);
        });

        it('should set `filterCounter` to 1 if `filterQuery` is not empty', function () {
            ctrl.onUpdateFiltersCounter('filter query');

            expect(ctrl.filtersCounter).toEqual(1);
        });
    });

    describe('openNewFunctionScreen(): ', function () {
        it('should call `$state.go` method', function () {
            spyOn($state, 'go').and.callThrough();

            ctrl.openNewFunctionScreen();

            expect($state.go).toHaveBeenCalledWith('app.create-function', {
                navigatedFrom: 'projects'
            });
        });
    });

    describe('openNewProjectDialog(): ', function () {
        it('should open ngDialog and get project list', function () {
            spyOn(ctrl, 'getProjects').and.callThrough();
            spyOn(ngDialog, 'open').and.returnValue({
                closePromise: $q.when({
                    value: 'some-value'
                })
            });

            ctrl.openNewProjectDialog();
            $rootScope.$digest();

            expect(ngDialog.open).toHaveBeenCalled();
            expect(ctrl.getProjects).toHaveBeenCalled();
        });
    });

    describe('refreshProjects(): ', function () {
        it('should change value of `ctrl.isFiltersShowed` and call `ctrl.getProjects()`', function () {
            spyOn(ctrl, 'getProjects').and.callThrough();

            ctrl.refreshProjects();
            $rootScope.$digest();

            expect(ctrl.getProjects).toHaveBeenCalled();
        });
    });

    describe('sortTableByColumn(): ', function () {
        it('should set reverse sorting for the same column', function () {
            ctrl.sortedColumnName = 'some-test-column';
            ctrl.isReverseSorting = false;

            ctrl.sortTableByColumn('some-test-column');

            expect(ctrl.sortedColumnName).toBe('some-test-column');
            expect(ctrl.isReverseSorting).toBeTruthy();

            ctrl.sortTableByColumn('some-test-column');

            expect(ctrl.sortedColumnName).toBe('some-test-column');
            expect(ctrl.isReverseSorting).toBeFalsy();
        });

        it('should set sorting for the new column', function () {
            ctrl.sortedColumnName = 'some-test-column';
            ctrl.isReverseSorting = true;

            ctrl.sortTableByColumn('new-column');

            expect(ctrl.sortedColumnName).toBe('new-column');
            expect(ctrl.isReverseSorting).toBeFalsy();
        });
    });

    describe('toggleFilters(): ', function () {
        it('should change value of `ctrl.isFiltersShowed`', function () {
            ctrl.isFiltersShowed.value = false;

            ctrl.toggleFilters();

            expect(ctrl.isFiltersShowed.value).toBeTruthy();

            ctrl.toggleFilters();

            expect(ctrl.isFiltersShowed.value).toBeFalsy();
        });
    });
});
