package org.iatoki.judgels.uriel.controllers;
import org.iatoki.judgels.FileInfo;
import org.iatoki.judgels.play.InternalLink;
import org.iatoki.judgels.play.LazyHtml;
import org.iatoki.judgels.play.controllers.AbstractJudgelsController;
import org.iatoki.judgels.uriel.Contest;
import org.iatoki.judgels.uriel.forms.ContestFileUploadForm;
import org.iatoki.judgels.uriel.ContestNotFoundException;
import org.iatoki.judgels.uriel.services.ContestFileService;
import org.iatoki.judgels.uriel.services.ContestService;
import org.iatoki.judgels.uriel.controllers.securities.Authenticated;
import org.iatoki.judgels.uriel.controllers.securities.HasRole;
import org.iatoki.judgels.uriel.controllers.securities.LoggedIn;
import org.iatoki.judgels.uriel.views.html.contest.file.listFilesView;
import play.data.Form;
import play.db.jpa.Transactional;
import play.filters.csrf.AddCSRFToken;
import play.filters.csrf.RequireCSRFCheck;
import play.i18n.Messages;
import play.mvc.Controller;
import play.mvc.Http;
import play.mvc.Result;
import play.mvc.Results;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
@Authenticated(value = {LoggedIn.class, HasRole.class})
@Singleton
@Named
public final class ContestFileController extends AbstractJudgelsController {
private final ContestService contestService;
private final ContestFileService contestFileService;
@Inject
public ContestFileController(ContestService contestService, ContestFileService contestFileService) {
this.contestService = contestService;
this.contestFileService = contestFileService;
}
@Transactional(readOnly = true)
@AddCSRFToken
public Result viewFiles(long contestId) throws ContestNotFoundException {
return listFiles(contestId);
}
@Transactional(readOnly = true)
@AddCSRFToken
public Result listFiles(long contestId) throws ContestNotFoundException {
Contest contest = contestService.findContestById(contestId);
if (isAllowedToManageFiles(contest)) {
Form<ContestFileUploadForm> form = Form.form(ContestFileUploadForm.class);
List<FileInfo> fileInfos = contestFileService.getContestFiles(contest.getJid());
return showListFiles(form, contest, fileInfos);
} else {
return ContestControllerUtils.getInstance().tryEnteringContest(contest);
}
}
@Transactional
@RequireCSRFCheck
public Result postUploadFile(long contestId) throws ContestNotFoundException{
Contest contest = contestService.findContestById(contestId);
if (isAllowedToManageFiles(contest)) {
Form<ContestFileUploadForm> form = Form.form(ContestFileUploadForm.class).bindFromRequest();
if (form.hasErrors() || form.hasGlobalErrors()) {
List<FileInfo> fileInfos = contestFileService.getContestFiles(contest.getJid());
return showListFiles(form, contest, fileInfos);
} else {
Http.MultipartFormData body = request().body().asMultipartFormData();
Http.MultipartFormData.FilePart file;
file = body.getFile("file");
if (file != null) {
File contestFile = file.getFile();
try {
contestFileService.uploadContestFile(contest.getJid(), contestFile, file.getFilename());
return redirect(routes.ContestFileController.viewFiles(contest.getId()));
} catch (IOException e) {
form.reject("file.cannotUploadFile");
List<FileInfo> fileInfos = contestFileService.getContestFiles(contest.getJid());
return showListFiles(form, contest, fileInfos);
}
}
List<FileInfo> fileInfos = contestFileService.getContestFiles(contest.getJid());
return showListFiles(form, contest, fileInfos);
}
} else {
return ContestControllerUtils.getInstance().tryEnteringContest(contest);
}
}
@Transactional(readOnly = true)
public Result downloadFile(long contestId, String filename, String any) throws ContestNotFoundException {
Contest contest = contestService.findContestById(contestId);
if (ContestControllerUtils.getInstance().isAllowedToEnterContest(contest)) {
String fileURL = contestFileService.getContestFileURL(contest.getJid(), filename);
try {
new URL(fileURL);
return redirect(fileURL);
} catch (MalformedURLException e) {
File file = new File(fileURL);
if (!file.exists()) {
return Results.notFound();
}
Controller.response().setContentType("application/x-download");
Controller.response().setHeader("Content-disposition", "attachment; filename=" + file.getName());
return ok(file);
}
} else {
return notFound();
}
}
private Result showListFiles(Form<ContestFileUploadForm> form, Contest contest, List<FileInfo> fileInfos) {
LazyHtml content = new LazyHtml(listFilesView.render(form, contest, fileInfos));
ContestControllerUtils.getInstance().appendTabsLayout(content, contest);
ControllerUtils.getInstance().appendSidebarLayout(content);
appendBreadcrumbsLayout(content, contest,
new InternalLink(Messages.get("file.list"), routes.ContestFileController.viewFiles(contest.getId()))
);
ControllerUtils.getInstance().appendTemplateLayout(content, "Contest - Files - List");
return ControllerUtils.getInstance().lazyOk(content);
}
private void appendBreadcrumbsLayout(LazyHtml content, Contest contest, InternalLink... lastLinks) {
ControllerUtils.getInstance().appendBreadcrumbsLayout(content,
ContestControllerUtils.getInstance().getContestBreadcrumbsBuilder(contest)
.add(new InternalLink(Messages.get("file.files"), routes.ContestController.jumpToFiles(contest.getId())))
.addAll(Arrays.asList(lastLinks))
.build()
);
}
private boolean isAllowedToManageFiles(Contest contest) {
return ContestControllerUtils.getInstance().isSupervisorOrAbove(contest);
}
}