package com.plannaplan.services;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import com.plannaplan.entities.Assignment;
import com.plannaplan.entities.Commision;
import com.plannaplan.entities.Groups;
import com.plannaplan.entities.User;
import com.plannaplan.models.EmailAcceptedData;
import com.plannaplan.repositories.AssignmentRepository;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * Service of Assignment which can save assignments, diplay assignments, get
 * ammount of assigments.
 */

@Service
public class AssignmentService {
    @Autowired
    private AssignmentRepository repo;

    @Autowired
    private CommisionService service;

    @Autowired
    private UserService userService;

    @Autowired
    private EmailService emailService;

    public AssignmentService() {
    }

    /**
     * Save given assignment
     * 
     * @param assignment assignment to save
     * @return assignment saved assignment with database id
     */
    public Assignment save(Assignment assignment) {
        return this.repo.save(assignment);
    }

    /**
     * gets list of assignments of given commision
     * 
     * @param com Commision to get assinments from
     * @return list of assignments
     */
    public List<Assignment> getCommisionAssignments(Commision com) {
        return this.repo.getByCommision(com.getId());
    }

    /**
     * get ammount of all assignments (not only for selected commision)
     * 
     * @return long - ammount of assingments
     */
    public long getAssignmentsAmmount() {
        return this.repo.count();
    }

    /**
     * Get assigmnent by id
     * 
     * @param id id of assigmnent
     * @return Optional of assignment
     */
    public Optional<Assignment> getById(Long id) {
        return this.repo.findById(id);
    }

    /**
     * this method will activate accept algorythm for all students. Algorythm is
     * takeing each student in order defined by ranking and accept for him groups
     * that are joinable for him
     */
    public void callAcceptAlgorythm() {
        final List<User> students = this.userService.getStudentsSortedByRanking();

        students.forEach(e -> {
            final Optional<Commision> com = this.service.getNewestCommision(e);
            final List<Groups> accepted = new ArrayList<>();
            final List<Groups> removed = new ArrayList<>();

            if (com.isPresent()) {
                final List<Assignment> assignments = this.getCommisionAssignments(com.get());
                assignments.forEach(a -> {
                    if (a.isAccepted() == false) {
                        final Groups group = a.getGroup();
                        if (group.getCapacity() > group.getRegisteredStudents().size()) {
                            e.claimGroup(group);
                            accepted.add(group);
                        } else {
                            removed.add(group);
                        }
                    }
                });
            }
            this.userService.save(e);
            this.emailService.sendAcceptationResult(e, new EmailAcceptedData(accepted, removed));
        });
    }
}