package de.learny.controller;
import io.swagger.annotations.Api;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.annotation.JsonView;
import de.learny.JsonView.View;
import de.learny.controller.exception.NotEnoughPermissionsException;
import de.learny.controller.exception.NotJoinedSubject;
import de.learny.controller.exception.ResourceNotFoundException;
import de.learny.dataaccess.TestRepository;
import de.learny.dataaccess.TestScoreRepository;
import de.learny.domain.Account;
import de.learny.domain.Answer;
import de.learny.domain.Question;
import de.learny.domain.Subject;
import de.learny.domain.Test;
import de.learny.domain.TestScore;
import de.learny.security.service.LoggedInAccountService;
import de.learny.service.NewTestScoreHandler;
@Api(value = "Tests", description = "Tests verwalten. Test ausfüllen. Testergebnisse einsehen", produces = "application/json")
@RestController
@RequestMapping("/api/tests")
public class TestController {
@Autowired
private TestRepository testRepository;
@Autowired
private LoggedInAccountService userToAccountService;
@Autowired
private TestScoreRepository testScoreRepo;
@Autowired
private NewTestScoreHandler newTestScoreHandler;
@RequestMapping(value = "", method = RequestMethod.GET)
Iterable<Test> getAllTests() {
return testRepository.findAll();
}
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
Test getTest(@PathVariable("id") long id) {
Test test = testRepository.findById(id);
if (test == null)
throw new ResourceNotFoundException("Ein Test mit diese id existiert nicht");
return test;
}
public TestRepository getTestRepository() {
return testRepository;
}
public void setTestRepository(TestRepository testRepository) {
this.testRepository = testRepository;
}
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
void delete(@PathVariable("id") long id) {
Test test = testRepository.findById(id);
if (test == null)
throw new ResourceNotFoundException("Ein Test mit diese id existiert nicht");
if (permitted(id)) {
this.testRepository.delete(id);
}
}
@RequestMapping(value = "/{id}", method = RequestMethod.PUT, consumes = { MediaType.APPLICATION_JSON_VALUE })
Test update(@PathVariable("id") long id, @RequestBody Test updateTest) {
// TODO: Was muss noch geupdatet werden?
Test oldTest = testRepository.findById(id);
if (oldTest == null)
throw new ResourceNotFoundException("Ein Fach mit dieser id existiert nicht");
if (permitted(id)) {
oldTest.setName(updateTest.getName());
}
return this.testRepository.save(oldTest);
}
@JsonView(View.Summary.class)
@RequestMapping(value = "/{id}/questions", method = RequestMethod.GET)
Iterable<Question> getAllQuestionsToTest(@PathVariable("id") long id) {
Test test = testRepository.findById(id);
if (test == null)
throw new ResourceNotFoundException("Ein Fach mit dieser id existiert nicht");
return test.getQuestions();
}
@RequestMapping(value = "/{id}/results", method = RequestMethod.GET)
Iterable<TestScore> getResultsFromTest(@PathVariable("id") long id) {
Test test = testRepository.findById(id);
if (test == null)
throw new ResourceNotFoundException("Ein Fach mit dieser id existiert nicht");
return test.getTestScores();
}
@RequestMapping(value = "/{id}/results", method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE })
void turnTest(@PathVariable("id") long id,
@RequestBody Set<Question> questions) {
Test test = testRepository.findById(id);
if (test == null)
throw new ResourceNotFoundException("Ein Test mit dieser id existiert nicht");
Account loggedInAccount = userToAccountService.getLoggedInAccount();
if(!loggedInAccount.getJoinedSubjects().contains(test.getSubject())){
throw new NotJoinedSubject("Sie sind nicht in dem Fach angemeldet");
}
TestScore oldTestScore = testScoreRepo.findByAccountAndTest(loggedInAccount, test);
if(oldTestScore != null){
testScoreRepo.delete(oldTestScore);
}
TestScore testScore = new TestScore(test, loggedInAccount, questions);
newTestScoreHandler.addNew(testScore, questions);
}
@JsonView(View.Summary.class)
@RequestMapping(value = "/{id}/highscore", method = RequestMethod.GET)
Iterable<TestScore> getHighscoreFromTest(@PathVariable("id") long id) {
Test test = testRepository.findById(id);
if (test == null)
throw new ResourceNotFoundException("Ein Fach mit dieser id existiert nicht");
return testScoreRepo.findTop10ByTestOrderByScoreDesc(test);
}
@RequestMapping(value = "/{id}/myLatestResult", method = RequestMethod.GET)
TestScore myLatestResult(@PathVariable("id") long id) {
Test test = testRepository.findById(id);
if (test == null)
throw new ResourceNotFoundException("Ein Fach mit dieser id existiert nicht");
Account loggedInAccount = userToAccountService.getLoggedInAccount();
return testScoreRepo.findFirstByAccountAndTestOrderByTimestampDesc(loggedInAccount, test);
}
private boolean permitted(long id) {
Test test = testRepository.findById(id);
Account loggedInAccount = userToAccountService.getLoggedInAccount();
boolean inCharge = false;
Subject subject = test.getSubject();
inCharge = subject.getAccountsInCharge().contains(loggedInAccount);
if (inCharge || loggedInAccount.hasRole("admin")) {
return true;
} else {
throw new NotEnoughPermissionsException("Nicht genug Rechte, um das auszuführen.");
}
}
}