package controllers;
import controllers.Navigation.Level;
import managers.AccountManager;
import managers.GroupManager;
import managers.PostManager;
import models.Account;
import models.Group;
import models.Post;
import models.services.ElasticsearchResponse;
import models.services.ElasticsearchService;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.NoNodeAvailableException;
import play.Configuration;
import play.Logger;
import play.api.i18n.Lang;
import play.data.Form;
import play.data.FormFactory;
import play.db.jpa.Transactional;
import play.i18n.MessagesApi;
import play.mvc.Result;
import play.mvc.Security;
import play.routing.JavaScriptReverseRouter;
import views.html.*;
import views.html.snippets.streamRaw;
import javax.inject.Inject;
import java.util.HashMap;
import java.util.concurrent.ExecutionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.util.Arrays.asList;
@Transactional
public class Application extends BaseController {
ElasticsearchService elasticsearchService;
ElasticsearchResponse elasticsearchResponse;
GroupManager groupManager;
PostManager postManager;
AccountManager accountManager;
Configuration configuration;
FormFactory formFactory;
MessagesApi messagesApi;
@Inject
public Application(ElasticsearchService elasticsearchService,
ElasticsearchResponse elasticsearchResponse,
GroupManager groupManager,
PostManager postManager,
AccountManager accountManager,
Configuration configuration,
FormFactory formFactory,
MessagesApi messagesApi) {
this.elasticsearchService = elasticsearchService;
this.elasticsearchResponse = elasticsearchResponse;
this.groupManager = groupManager;
this. postManager = postManager;
this.accountManager = accountManager;
this.configuration = configuration;
this.messagesApi = messagesApi;
this.formFactory = formFactory;
this.postForm = formFactory.form(Post.class);
this.limit = configuration.getInt("htwplus.post.limit");
}
Form<Post> postForm;
int limit;
static final int PAGE = 1;
public Result javascriptRoutes() {
return ok(
JavaScriptReverseRouter.create("jsRoutes",
controllers.routes.javascript.GroupController.create(),
controllers.routes.javascript.GroupController.update()
)
).as("text/javascript");
}
@Security.Authenticated(Secured.class)
public Result index() {
Navigation.set(Level.STREAM, "Alles");
Account currentAccount = Component.currentAccount();
return ok(stream.render(currentAccount, postManager.getStream(currentAccount, limit, PAGE), postForm, postManager.countStream(currentAccount, ""), limit, PAGE, "all"));
}
public Result help() {
Navigation.set(Level.HELP);
return ok(help.render());
}
@Security.Authenticated(Secured.class)
public Result stream(String filter, int page, boolean raw) {
Account currentAccount = Component.currentAccount();
// filter must be set for pagination
// cant do it in routes, routes.Application.stream(filter, 1).toString would truncate it
if(StringUtils.isEmpty(filter)) {
filter = "all";
}
switch (filter) {
case "account":
Navigation.set(Level.STREAM, "Eigene Posts");
break;
case "group":
Navigation.set(Level.STREAM, "Gruppen");
break;
case "contact":
Navigation.set(Level.STREAM, "Kontakte");
break;
case "bookmark":
Navigation.set(Level.STREAM, "Gemerkte Posts");
break;
default:
Navigation.set(Level.STREAM, "Alles");
filter = "all";
}
if (raw) {
return ok(streamRaw.render(postManager.getFilteredStream(currentAccount, limit, page, filter), postForm, postManager.countStream(currentAccount, filter), limit, page, filter));
} else {
return ok(stream.render(currentAccount, postManager.getFilteredStream(currentAccount, limit, page, filter), postForm, postManager.countStream(currentAccount, filter), limit, page, filter));
}
}
@Security.Authenticated(Secured.class)
public Result searchSuggestions(String query) throws ExecutionException, InterruptedException {
Account currentAccount = Component.currentAccount();
if (currentAccount == null) {
return forbidden();
}
SearchResponse response = elasticsearchService.doSearch("searchSuggestions", query, "all", null, 1, currentAccount.id.toString(), asList("name", "title", "filename"), asList("friends", "member", "viewable"));
return ok(response.toString());
}
@Security.Authenticated(Secured.class)
public Result searchHome() {
Navigation.set(Level.SEARCH);
return ok(views.html.Search.search.render());
}
@Security.Authenticated(Secured.class)
public Result search(int page) throws ExecutionException, InterruptedException {
Account currentAccount = Component.currentAccount();
String keyword = formFactory.form().bindFromRequest().field("keyword").value();
String mode = formFactory.form().bindFromRequest().field("mode").value();
String studycourseParam = formFactory.form().bindFromRequest().field("studycourse").value();
String degreeParam = formFactory.form().bindFromRequest().field("degree").value();
String semesterParam = formFactory.form().bindFromRequest().field("semester").value();
String roleParam = formFactory.form().bindFromRequest().field("role").value();
String grouptypeParam = formFactory.form().bindFromRequest().field("grouptype").value();
HashMap<String, String[]> facets = new HashMap<>();
facets.put("studycourse", buildUserFacetList(studycourseParam));
facets.put("degree", buildUserFacetList(degreeParam));
facets.put("semester", buildUserFacetList(semesterParam));
facets.put("role", buildUserFacetList(roleParam));
facets.put("grouptype", buildUserFacetList(grouptypeParam));
if (keyword == null) {
flash("info", "Nach was suchst du?");
return redirect(controllers.routes.Application.searchHome());
}
if (mode == null) mode = "all";
Pattern pt = Pattern.compile("[^ a-zA-Z0-9\u00C0-\u00FF]");
Matcher match = pt.matcher(keyword);
while (match.find()) {
String s = match.group();
keyword = keyword.replaceAll("\\" + s, "");
flash("info", "Dein Suchwort enthielt ungültige Zeichen, die für die Suche entfernt wurden!");
}
SearchResponse response;
try {
response = elasticsearchService.doSearch("search", keyword.toLowerCase(), mode, facets, page, currentAccount.id.toString(), asList("name", "title", "content", "filename"), asList("friends", "owner", "member", "viewable"));
elasticsearchResponse.create(response, keyword, mode);
} catch (NoNodeAvailableException nna) {
flash("error", "Leider steht die Suche zur Zeit nicht zur Verfügung!");
return ok(views.html.Search.search.render());
}
Navigation.set(Level.SEARCH, elasticsearchResponse.getDocumentCount() + " Ergebnisse zu \""+ keyword +"\"");
if (!mode.isEmpty() && !mode.equals("all")) {
Navigation.set(Level.SEARCH, elasticsearchResponse.getDocumentCount() + " Ergebnisse zu \""+ keyword +"\"", messagesApi.get(Lang.defaultLang(), "search."+mode), null);
}
return ok(views.html.Search.searchresult.render(
page,
limit,
elasticsearchResponse));
}
public Result error() {
Navigation.set("404");
return ok(error.render());
}
@Security.Authenticated(Secured.class)
public Result feedback() {
final String feedbackGroup = configuration.getString("htwplus.feedback.group");
Group feedback = groupManager.findByTitle(feedbackGroup);
if (feedback != null) {
return redirect(controllers.routes.GroupController.view(feedback.id));
}
return notFound();
}
public Result imprint() {
Navigation.set("Impressum");
return ok(imprint.render());
}
public Result privacy() {
Navigation.set("Datenschutzerklärung");
return ok(privacy.render());
}
public Result defaultRoute(String path) {
Logger.info(path + " nicht gefunden");
return redirect(controllers.routes.Application.index());
}
private String[] buildUserFacetList(String parameter) {
if (parameter != null) {
return parameter.split(",");
}
return new String[0];
}
}