(function () {

'use strict';

angular.module('OpenSlidesApp.assignments.site', [
    'OpenSlidesApp.assignments',
    'OpenSlidesApp.core.pdf',
    'OpenSlidesApp.assignments.pdf',
    'OpenSlidesApp.poll.majority'
])

.config([
    'mainMenuProvider',
    'gettext',
    function (mainMenuProvider, gettext) {
        mainMenuProvider.register({
            'ui_sref': 'assignments.assignment.list',
            'img_class': 'pie-chart',
            'title': gettext('Elections'),
            'weight': 400,
            'perm': 'assignments.can_see'
        });
    }
])

.config([
    'SearchProvider',
    'gettext',
    function (SearchProvider, gettext) {
        SearchProvider.register({
            'verboseName': gettext('Elections'),
            'collectionName': 'assignments/assignment',
            'urlDetailState': 'assignments.assignment.detail',
            'weight': 400,
        });
    }
])

.config([
    '$stateProvider',
    'gettext',
    function($stateProvider, gettext) {
        $stateProvider
            .state('assignments', {
                url: '/assignments',
                abstract: true,
                template: "<ui-view/>",
                data: {
                    title: gettext('Elections'),
                    basePerm: 'assignments.can_see',
                },
            })
            .state('assignments.assignment', {
                abstract: true,
                template: "<ui-view/>",
            })
            .state('assignments.assignment.list', {})
            .state('assignments.assignment.detail', {
                controller: 'AssignmentDetailCtrl',
                resolve: {
                    assignmentId: ['$stateParams', function($stateParams) {
                        return $stateParams.id;
                    }],
                }
            })
            // redirects to assignment detail and opens assignment edit form dialog, uses edit url,
            // used by ui-sref links from agenda only
            // (from assignment controller use AssignmentForm factory instead to open dialog in front
            // of current view without redirect)
            .state('assignments.assignment.detail.update', {
                onEnter: ['$stateParams', '$state', 'ngDialog',
                    function($stateParams, $state, ngDialog) {
                        ngDialog.open({
                            template: 'static/templates/assignments/assignment-form.html',
                            controller: 'AssignmentUpdateCtrl',
                            className: 'ngdialog-theme-default wide-form',
                            closeByEscape: false,
                            closeByDocument: false,
                            resolve: {
                                assignmentId: function() {
                                    return $stateParams.id;
                                },
                            },
                            preCloseCallback: function() {
                                $state.go('assignments.assignment.detail', {assignment: $stateParams.id});
                                return true;
                            }
                        });
                    }
                ]
            });
    }
])

// Service for generic assignment form (create and update)
.factory('AssignmentForm', [
    'gettextCatalog',
    'operator',
    'Editor',
    'Mediafile',
    'Tag',
    'Assignment',
    'Agenda',
    'AgendaTree',
    'ShowAsAgendaItemField',
    function (gettextCatalog, operator, Editor, Mediafile, Tag, Assignment, Agenda, AgendaTree, ShowAsAgendaItemField) {
        return {
            // ngDialog for assignment form
            getDialog: function (assignment) {
                return {
                    template: 'static/templates/assignments/assignment-form.html',
                    controller: (assignment) ? 'AssignmentUpdateCtrl' : 'AssignmentCreateCtrl',
                    className: 'ngdialog-theme-default wide-form',
                    closeByEscape: false,
                    closeByDocument: false,
                    resolve: {
                        assignmentId: function () {return assignment ? assignment.id : void 0;}
                    },
                };
            },
            // angular-formly fields for assignment form
            getFormFields: function (isCreateForm) {
                var images = Mediafile.getAllImages();
                var formFields = [
                {
                    key: 'title',
                    type: 'input',
                    templateOptions: {
                        label: gettextCatalog.getString('Title'),
                        required: true
                    }
                },
                {
                    key: 'description',
                    type: 'editor',
                    templateOptions: {
                        label: gettextCatalog.getString('Description')
                    },
                    data: {
                        ckeditorOptions: Editor.getOptions(images)
                    }
                },
                {
                    key: 'open_posts',
                    type: 'input',
                    templateOptions: {
                        label: gettextCatalog.getString('Number of persons to be elected'),
                        type: 'number',
                        min: 1,
                        required: true
                    }
                },
                {
                    key: 'poll_description_default',
                    type: 'input',
                    templateOptions: {
                        label: gettextCatalog.getString('Default comment on the ballot paper')
                    }
                }];

                // show as agenda item + parent item
                if (isCreateForm) {
                    formFields.push(ShowAsAgendaItemField('assignments.can_manage'));
                    formFields.push({
                        key: 'agenda_parent_id',
                        type: 'select-single',
                        templateOptions: {
                            label: gettextCatalog.getString('Parent item'),
                            options: AgendaTree.getFlatTree(Agenda.getAll()),
                            ngOptions: 'item.id as item.getListViewTitle() for item in to.options | notself : model.agenda_item_id',
                            placeholder: gettextCatalog.getString('Select a parent item ...')
                        },
                        hide: !operator.hasPerms('agenda.can_manage')
                    });
                }
                // more (with tags field)
                if (Tag.getAll().length > 0) {
                    formFields.push(
                        {
                            key: 'more',
                            type: 'checkbox',
                            templateOptions: {
                                label: gettextCatalog.getString('Show extended fields')
                            },
                            hide: !operator.hasPerms('assignments.can_manage')
                        },
                        {
                            template: '<hr class="smallhr">',
                            hideExpression: '!model.more'
                        },
                        {
                            key: 'tags_id',
                            type: 'select-multiple',
                            templateOptions: {
                                label: gettextCatalog.getString('Tags'),
                                options: Tag.getAll(),
                                ngOptions: 'option.id as option.name for option in to.options',
                                placeholder: gettextCatalog.getString('Select or search a tag ...')
                            },
                            hideExpression: '!model.more'
                        }
                    );
                }

                return formFields;
            }
        };
    }
])

// Cache for AssignmentPollDetailCtrl so that users choices are keeped during user actions (e. g. save poll form).
.value('AssignmentPollDetailCtrlCache', {})

// Child controller of AssignmentDetailCtrl for each single poll.
.controller('AssignmentPollDetailCtrl', [
    '$scope',
    'MajorityMethodChoices',
    'Config',
    'AssignmentPollDetailCtrlCache',
    'AssignmentPoll',
    'AssignmentPollDecimalPlaces',
    function ($scope, MajorityMethodChoices, Config, AssignmentPollDetailCtrlCache,
        AssignmentPoll, AssignmentPollDecimalPlaces) {
        // Define choices.
        $scope.methodChoices = MajorityMethodChoices;
        // TODO: Get $scope.baseChoices from config_variables.py without copying them.

        $scope.votesPrecision = AssignmentPollDecimalPlaces.getPlaces($scope.poll);

        // Setup empty cache with default values.
        if (typeof AssignmentPollDetailCtrlCache[$scope.poll.id] === 'undefined') {
            AssignmentPollDetailCtrlCache[$scope.poll.id] = {
                method: $scope.config('assignments_poll_default_majority_method'),
            };
        }

        // Fetch users choices from cache.
        $scope.method = AssignmentPollDetailCtrlCache[$scope.poll.id].method;

        $scope.recalculateMajorities = function (method) {
            $scope.method = method;
            _.forEach($scope.poll.options, function (option) {
                option.majorityReached = option.isReached(method);
            });
        };
        $scope.recalculateMajorities($scope.method);

        $scope.saveDescriptionChange = function (poll) {
            AssignmentPoll.save(poll);
        };

        // Save current values to cache on destroy of this controller.
        $scope.$on('$destroy', function() {
            AssignmentPollDetailCtrlCache[$scope.poll.id] = {
                method: $scope.method,
            };
        });
    }
])

.controller('AssignmentListCtrl', [
    '$scope',
    'ngDialog',
    'AssignmentForm',
    'Assignment',
    'Tag',
    'Agenda',
    'Projector',
    'ProjectionDefault',
    'gettextCatalog',
    'User',
    'osTableFilter',
    'osTableSort',
    'osTablePagination',
    'gettext',
    'AssignmentPhases',
    'AssignmentPdfExport',
    function($scope, ngDialog, AssignmentForm, Assignment, Tag, Agenda, Projector,
        ProjectionDefault, gettextCatalog, User, osTableFilter, osTableSort, osTablePagination,
        gettext, AssignmentPhases, AssignmentPdfExport) {
        $scope.$watch(function () {
            return Assignment.lastModified();
        }, function () {
            $scope.assignments = _.orderBy(Assignment.getAll(), ['title']);
        });
        Tag.bindAll({}, $scope, 'tags');
        $scope.$watch(function () {
            return Projector.lastModified();
        }, function () {
            var projectiondefault = ProjectionDefault.filter({name: 'assignments'})[0];
            if (projectiondefault) {
                $scope.defaultProjectorId = projectiondefault.projector_id;
            }
        });
        $scope.phases = AssignmentPhases;
        $scope.alert = {};

        // Filtering
        $scope.filter = osTableFilter.createInstance('AssignmentTableFilter');

        if (!$scope.filter.existsStorageEntry()) {
            $scope.filter.multiselectFilters = {
                tag: [],
                phase: [],
            };
        }
        $scope.filter.propertyList = ['title', 'description'];
        $scope.filter.propertyFunctionList = [
            function (assignment) {
                return gettextCatalog.getString($scope.phases[assignment.phase].display_name);
            },
        ];
        $scope.filter.propertyDict = {
            'assignment_related_users': function (candidate) {
                return candidate.user.get_short_name();
            },
            'tags': function (tag) {
                return tag.name;
            },
        };
        $scope.getItemId = {
            tag: function (assignment) {return assignment.tags_id;},
            phase: function (assignment) {return assignment.phase;},
        };

        // Sorting
        $scope.sort = osTableSort.createInstance('AssignmentTableSort');
        if (!$scope.sort.column) {
            $scope.sort.column = 'title';
        }
        $scope.sortOptions = [
            {name: 'agenda_item.getItemNumberWithAncestors()',
             display_name: gettext('Item')},
            {name: 'title',
             display_name: gettext('Title')},
            {name: 'phase',
             display_name: gettext('Phase')},
            {name: 'assignment_related_users.length',
             display_name: gettext('Number of candidates')},
        ];
        $scope.hasTag = function (assignment, tag) {
            return _.indexOf(assignment.tags_id, tag.id) > -1;
        };
        $scope.toggleTag = function (assignment, tag) {
            if ($scope.hasTag(assignment, tag)) {
                assignment.tags_id = _.filter(assignment.tags_id, function (tag_id){
                    return tag_id != tag.id;
                });
            } else {
                assignment.tags_id.push(tag.id);
            }
            Assignment.save(assignment);
        };

        // Pagination
        $scope.pagination = osTablePagination.createInstance('AssignmentTablePagination');

        // update phase
        $scope.updatePhase = function (assignment, phase_id) {
            assignment.phase = phase_id;
            Assignment.save(assignment);
        };
        // open new/edit dialog
        $scope.openDialog = function (assignment) {
            ngDialog.open(AssignmentForm.getDialog(assignment));
        };
        // *** select mode functions ***
        $scope.isSelectMode = false;
        // check all checkboxes
        $scope.checkAll = function () {
            $scope.selectedAll = !$scope.selectedAll;
            angular.forEach($scope.assignments, function (assignment) {
                assignment.selected = $scope.selectedAll;
            });
        };
        // uncheck all checkboxes if isSelectMode is closed
        $scope.uncheckAll = function () {
            if (!$scope.isSelectMode) {
                $scope.selectedAll = false;
                angular.forEach($scope.assignments, function (assignment) {
                    assignment.selected = false;
                });
            }
        };
        // delete all selected assignments
        $scope.deleteMultiple = function () {
            angular.forEach($scope.assignments, function (assignment) {
                if (assignment.selected)
                    Assignment.destroy(assignment.id);
            });
            $scope.isSelectMode = false;
            $scope.uncheckAll();
        };
        // delete single assignment
        $scope.delete = function (assignment) {
            Assignment.destroy(assignment.id);
        };
        // create the PDF List
        $scope.pdfExport = function () {
            AssignmentPdfExport.export($scope.assignmentsFiltered);
        };
    }
])

.controller('AssignmentDetailCtrl', [
    '$scope',
    '$http',
    '$filter',
    '$timeout',
    'filterFilter',
    'gettext',
    'ngDialog',
    'AssignmentForm',
    'operator',
    'Assignment',
    'User',
    'assignmentId',
    'Projector',
    'ProjectionDefault',
    'gettextCatalog',
    'AssignmentPhases',
    'AssignmentPdfExport',
    'WebpageTitle',
    'ErrorMessage',
    function($scope, $http, $filter, $timeout, filterFilter, gettext, ngDialog, AssignmentForm, operator,
        Assignment, User, assignmentId, Projector, ProjectionDefault, gettextCatalog, AssignmentPhases,
        AssignmentPdfExport, WebpageTitle, ErrorMessage) {
        User.bindAll({}, $scope, 'users');
        var assignment = Assignment.get(assignmentId);
        Assignment.loadRelations(assignment, 'agenda_item');
        // This flag is for setting 'activeTab' to recently added (last) ballot tab.
        // Set this flag, if ballots are added/removed. When the next autoupdate comes
        // in, the tabset will be updated.
        var updateBallotTabsFlag = true;
        $scope.$watch(function () {
            return Projector.lastModified();
        }, function () {
            var projectiondefault = ProjectionDefault.filter({name: 'assignments'})[0];
            if (projectiondefault) {
                $scope.defaultProjectorId = projectiondefault.projector_id;
            }
        });
        $scope.$watch(function () {
            return Assignment.lastModified(assignmentId);
        }, function () {
            // setup sorting of candidates
            $scope.relatedUsersSorted = $filter('orderBy')(assignment.assignment_related_users, 'weight');
            $scope.assignment = Assignment.get(assignment.id);
            if (updateBallotTabsFlag) {
                $scope.activeTab = $scope.assignment.polls.length - 1;
                updateBallotTabsFlag = false;
            }
            WebpageTitle.updateTitle(gettextCatalog.getString('Election') + ' ' + $scope.assignment.title);
        });
        $scope.candidateSelectBox = {};
        $scope.phases = AssignmentPhases;
        $scope.alert = {};

        // open edit dialog
        $scope.openDialog = function () {
            ngDialog.open(AssignmentForm.getDialog($scope.assignment));
        };
        // add (nominate) candidate
        $scope.addCandidate = function (userId) {
            $http.post('/rest/assignments/assignment/' + assignmentId + '/candidature_other/', {'user': userId})
                .then(function (success){
                    $scope.alert.show = false;
                    $scope.candidateSelectBox = {};
                }, function (error){
                    $scope.alert = ErrorMessage.forAlert(error);
                    $scope.candidateSelectBox = {};
                });
        };
        // remove candidate
        $scope.removeCandidate = function (userId) {
            $http.delete('/rest/assignments/assignment/' + assignmentId + '/candidature_other/',
                    {headers: {'Content-Type': 'application/json'},
                     data: JSON.stringify({user: userId})})
                .then(function (success) {},
                    function (error) {
                        $scope.alert = ErrorMessage.forAlert(error);
                    }
                );
        };
        // add me (nominate self as candidate)
        $scope.addMe = function () {
            $http.post('/rest/assignments/assignment/' + assignmentId + '/candidature_self/', {}).then(
                function (success) {
                    $scope.alert.show = false;
                }, function (error) {
                    $scope.alert = ErrorMessage.forAlert(error);
                }
            );
        };
        // remove me (withdraw own candidature)
        $scope.removeMe = function () {
            $http.delete('/rest/assignments/assignment/' + assignmentId + '/candidature_self/').then(
                function (success) {
                    $scope.alert.show = false;
                }, function (error) {
                    $scope.alert = ErrorMessage.forAlert(error);
                }
            );
        };
        // check if current user is already a candidate (elected==false)
        $scope.isCandidate = function () {
            var check = $scope.assignment.assignment_related_users.map(function(candidate) {
                if (!candidate.elected) {
                    return candidate.user_id;
                }
            }).indexOf(operator.user.id);
            if (check > -1) {
                return true;
            } else {
                return false;
            }
        };
        // Sort all candidates
        $scope.treeOptions = {
            dropped: function () {
                var sortedCandidates = [];
                _.forEach($scope.relatedUsersSorted, function (user) {
                    sortedCandidates.push(user.id);
                });
                $http.post('/rest/assignments/assignment/' + assignmentId + '/sort_related_users/',
                    {related_users: sortedCandidates}
                );
            }
        };
        // update phase
        $scope.updatePhase = function (phase_id) {
            $scope.assignment.phase = phase_id;
            Assignment.save($scope.assignment);
        };
        // create new ballot
        $scope.createBallot = function () {
            $http.post('/rest/assignments/assignment/' + assignmentId + '/create_poll/').then(
                function (success) {
                    $scope.alert.show = false;
                    if (assignment.phase === 0) {
                        $scope.updatePhase(1);
                    }
                    updateBallotTabsFlag = true;
                }, function (error) {
                    $scope.alert = ErrorMessage.forAlert(error);
                }
            );
        };
        // delete ballot
        $scope.deleteBallot = function (poll) {
            poll.DSDestroy().then(
                function (success) {
                    $scope.activeTab = $scope.activeTab - 1;
                    updateBallotTabsFlag = true;
                }
            );
        };
        // edit poll dialog
        $scope.editPollDialog = function (poll, ballot) {
            ngDialog.open({
                template: 'static/templates/assignments/assignmentpoll-form.html',
                controller: 'AssignmentPollUpdateCtrl',
                className: 'ngdialog-theme-default',
                closeByEscape: false,
                closeByDocument: false,
                resolve: {
                    assignmentpollId: function () {return poll.id;},
                    ballot: function () {return ballot;},
                }
            });
        };
        // publish ballot
        $scope.togglePublishBallot = function (poll) {
            poll.DSUpdate({
                    assignment_id: assignmentId,
                    published: !poll.published,
            })
            .then(function (success) {
                $scope.alert.show = false;
            }, function (error) {
                $scope.alert = ErrorMessage.forAlert(error);
            });
        };

        // mark candidate as (not) elected
        $scope.markElected = function (user, reverse) {
            if (reverse) {
                $http.delete(
                    '/rest/assignments/assignment/' + assignmentId + '/mark_elected/', {
                        headers: {
                            'Content-Type': 'application/json'
                        },
                        data: JSON.stringify({user: user})
                });
            } else {
                $http.post('/rest/assignments/assignment/' + assignmentId + '/mark_elected/', {'user': user});
            }

        };

        // Creates the document as pdf
        $scope.pdfExport = function() {
            AssignmentPdfExport.export($scope.assignment, true);
        };
        // Creates the ballotpaper as pdf
        $scope.ballotpaperExport = function(pollId) {
            AssignmentPdfExport.createBallotPdf($scope.assignment, pollId);
        };

        // Just mark some vote value strings for translation.
        gettext('Yes');
        gettext('No');
        gettext('Abstain');
    }
])

.controller('AssignmentCreateCtrl', [
    '$scope',
    '$state',
    'Assignment',
    'AssignmentForm',
    'Agenda',
    'Config',
    'ErrorMessage',
    function($scope, $state, Assignment, AssignmentForm, Agenda, Config, ErrorMessage) {
        $scope.model = {
            agenda_type: parseInt(Config.get('agenda_new_items_default_visibility').value),
        };
        // set default value for open posts form field
        $scope.model.open_posts = 1;
        // get all form fields
        $scope.formFields = AssignmentForm.getFormFields(true);
        // save assignment
        $scope.save = function(assignment, gotoDetailView) {
            Assignment.create(assignment).then(
                function (success) {
                    if (gotoDetailView) {
                        $state.go('assignments.assignment.detail', {id: success.id});
                    }
                    $scope.closeThisDialog();
                },
                function (error) {
                    $scope.alert = ErrorMessage.forAlert(error);
                }
            );
        };
    }
])

.controller('AssignmentUpdateCtrl', [
    '$scope',
    '$state',
    'Assignment',
    'AssignmentForm',
    'Agenda',
    'assignmentId',
    'ErrorMessage',
    function($scope, $state, Assignment, AssignmentForm, Agenda, assignmentId, ErrorMessage) {
        var assignment = Assignment.get(assignmentId);
        $scope.alert = {};
        // set initial values for form model by create deep copy of assignment object
        // so list/detail view is not updated while editing
        $scope.model = angular.copy(assignment);
        // get all form fields
        $scope.formFields = AssignmentForm.getFormFields();

        // save assignment
        $scope.save = function (assignment, gotoDetailView) {
            // inject the changed assignment (copy) object back into DS store
            Assignment.inject(assignment);
            // save changed assignment object on server
            Assignment.save(assignment).then(
                function(success) {
                    if (gotoDetailView) {
                        $state.go('assignments.assignment.detail', {id: success.id});
                    }
                    $scope.closeThisDialog();
                },
                function (error) {
                    // save error: revert all changes by restore
                    // (refresh) original assignment object from server
                    Assignment.refresh(assignment);
                    $scope.alert = ErrorMessage.forAlert(error);
                }
            );
        };
    }
])

.controller('AssignmentPollUpdateCtrl', [
    '$scope',
    '$filter',
    'gettextCatalog',
    'AssignmentPoll',
    'assignmentpollId',
    'AssignmentPollDecimalPlaces',
    'ballot',
    'ErrorMessage',
    function($scope, $filter, gettextCatalog, AssignmentPoll, assignmentpollId,
        AssignmentPollDecimalPlaces, ballot, ErrorMessage) {
        // set initial values for form model by create deep copy of assignmentpoll object
        // so detail view is not updated while editing poll
        var assignmentpoll = angular.copy(AssignmentPoll.get(assignmentpollId));
        $scope.model = assignmentpoll;
        $scope.ballot = ballot;
        $scope.formFields = [];
        $scope.alert = {};

        // For number inputs
        var step = Math.pow(10, -AssignmentPollDecimalPlaces.getPlaces(assignmentpoll));

        // add dynamic form fields
        var options = $filter('orderBy')(assignmentpoll.options, 'weight');
        _.forEach(options, function(option) {
            var defaultValue;
            if (assignmentpoll.pollmethod == 'yna' || assignmentpoll.pollmethod == 'yn') {
                defaultValue = {};
                _.forEach(option.votes, function (vote) {
                    defaultValue[vote.value.toLowerCase()] = vote.weight;
                });

                var columnClass = (assignmentpoll.pollmethod === 'yna') ? 'col-xs-4' : 'col-xs-6';
                var columns = [
                    {
                        key: 'yes_' + option.candidate_id,
                        type: 'input',
                        className: columnClass + ' no-padding-left',
                        templateOptions: {
                            label: gettextCatalog.getString('Yes'),
                            type: 'number',
                            min: -2,
                            step: step,
                            required: true
                        },
                        defaultValue: defaultValue.yes
                    },
                    {
                        key: 'no_' + option.candidate_id,
                        type: 'input',
                        className: columnClass + ' no-padding-left' +
                            (assignmentpoll.pollmethod === 'yn' ? ' no-padding-right' : ''),
                        templateOptions: {
                            label: gettextCatalog.getString('No'),
                            type: 'number',
                            min: -2,
                            step: step,
                            required: true
                        },
                        defaultValue: defaultValue.no
                    }
                ];
                if (assignmentpoll.pollmethod == 'yna'){
                    columns.push({
                        key:'abstain_' + option.candidate_id,
                        type: 'input',
                        className: columnClass + ' no-padding-left no-padding-right',
                        templateOptions: {
                            label: gettextCatalog.getString('Abstain'),
                            type: 'number',
                            min: -2,
                            step: step,
                            required: true
                        },
                        defaultValue: defaultValue.abstain
                    });
                }
                $scope.formFields.push({
                    noFormControl: true,
                    template: '<strong>' + option.candidate.get_full_name() + '</strong>'
                },
                {
                    className: 'row',
                    fieldGroup: columns,
                });
            } else { // votes method
                if (option.votes.length) {
                    defaultValue = option.votes[0].weight;
                }
                $scope.formFields.push({
                    key: 'vote_' + option.candidate_id,
                    type: 'input',
                    templateOptions: {
                        label: option.candidate.get_full_name(),
                        type: 'number',
                        min: -2,
                        step: step,
                        required: true,
                    },
                    defaultValue: defaultValue
                });
            }
        });
        if (assignmentpoll.pollmethod == 'votes'){
            $scope.formFields.push(
                {
                    key: 'votesabstain',
                    type: 'input',
                    templateOptions: {
                        label: gettextCatalog.getString('Abstain'),
                        type: 'number',
                        step: step,
                        min: -2,
                    }
                },
                {
                    key: 'votesno',
                    type: 'input',
                    templateOptions: {
                        label: gettextCatalog.getString('No'),
                        type: 'number',
                        step: step,
                        min: -2,
                    }
                }
            );
        }
        // add general form fields
        $scope.formFields.push(
            {
                template: '<hr class="smallhr">',
            },
            {
                key: 'votesvalid',
                type: 'input',
                templateOptions: {
                    label: gettextCatalog.getString('Valid ballots'),
                    type: 'number',
                    step: step,
                    min: -2,
                }
            },
            {
                key: 'votesinvalid',
                type: 'input',
                templateOptions: {
                    label: gettextCatalog.getString('Invalid ballots'),
                    type: 'number',
                    step: step,
                    min: -2,
                }
            },
            {
                key: 'votescast',
                type: 'input',
                templateOptions: {
                    label: gettextCatalog.getString('Casted ballots'),
                    type: 'number',
                    step: step,
                    min: -2,
                }
            }
        );

        // save assignmentpoll
        $scope.save = function (poll) {
            var votes = [];
            if (assignmentpoll.pollmethod == 'yna') {
                assignmentpoll.options.forEach(function(option) {
                    votes.push({
                        'Yes': poll['yes_' + option.candidate_id],
                        'No': poll['no_' + option.candidate_id],
                        'Abstain': poll['abstain_' + option.candidate_id]
                    });
                });
            } else if (assignmentpoll.pollmethod == 'yn') {
                    assignmentpoll.options.forEach(function(option) {
                        votes.push({
                            'Yes': poll['yes_' + option.candidate_id],
                            'No': poll['no_' + option.candidate_id]
                            });
                        });
            } else {
                assignmentpoll.options.forEach(function(option) {
                    votes.push({
                        'Votes': poll['vote_' + option.candidate_id],
                    });
                });
            }
            // save change poll object on server
            poll.DSUpdate({
                assignment_id: poll.assignment_id,
                votes: votes,
                votesabstain: poll.votesabstain,
                votesno: poll.votesno,
                votesvalid: poll.votesvalid,
                votesinvalid: poll.votesinvalid,
                votescast: poll.votescast,
            })
            .then(function(success) {
                $scope.alert.show = false;
                $scope.closeThisDialog();
            }, function (error) {
                $scope.alert = ErrorMessage.forAlert(error);
            });
        };
    }
])

//mark all assignment config strings for translation with Javascript
.config([
    'gettext',
    function (gettext) {
        gettext('Election method');
        gettext('Automatic assign of method');
        gettext('Always one option per candidate');
        gettext('Always Yes-No-Abstain per candidate');
        gettext('Always Yes/No per candidate');
        gettext('Elections');
        gettext('Ballot and ballot papers');
        gettext('The 100-%-base of an election result consists of');
        gettext('For Yes/No/Abstain per candidate and Yes/No per candidate the 100-%-base ' +
                'depends on the election method: If there is only one option per candidate, ' +
                'the sum of all votes of all candidates is 100 %. Otherwise for each ' +
                'candidate the sum of all votes is 100 %.');
        gettext('Yes/No/Abstain per candidate');
        gettext('Yes/No per candidate');
        gettext('All valid ballots');
        gettext('All casted ballots');
        gettext('Disabled (no percents)');
        gettext('Number of ballot papers (selection)');
        gettext('Number of all delegates');
        gettext('Number of all participants');
        gettext('Use the following custom number');
        gettext('Custom number of ballot papers');
        gettext('Required majority');
        gettext('Default method to check whether a candidate has reached the required majority.');
        gettext('Simple majority');
        gettext('Two-thirds majority');
        gettext('Three-quarters majority');
        gettext('Disabled');
        gettext('Put all candidates on the list of speakers');
        gettext('Title for PDF document (all elections)');
        gettext('Preamble text for PDF document (all elections)');
        //other translations
        gettext('Searching for candidates');
        gettext('Voting');
        gettext('Finished');
    }
]);

}());
