/**
 * 
 */
package de.bstly.board.controller;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.google.common.collect.Lists;

import de.bstly.board.businesslogic.CommentManager;
import de.bstly.board.businesslogic.EntryManager;
import de.bstly.board.businesslogic.FlagManager;
import de.bstly.board.businesslogic.SettingsManager;
import de.bstly.board.businesslogic.UserManager;
import de.bstly.board.controller.support.EntityResponseStatusException;
import de.bstly.board.model.Comment;
import de.bstly.board.model.Entry;
import de.bstly.board.model.LocalUser;
import de.bstly.board.model.support.Types;

/**
 * The Class ModerationController.
 */
@RestController
@RequestMapping("/moderation")
public class ModerationController extends BaseController {

	@Autowired
	private CommentManager commentManager;
	@Autowired
	private EntryManager entryManager;
	@Autowired
	private UserManager userManager;
	@Autowired
	private FlagManager flagManager;
	@Autowired
	private SettingsManager settingsManager;

	/**
	 * Gets the flagged comments.
	 *
	 * @param pageParameter the page parameter
	 * @param sizeParameter the size parameter
	 * @param ascParameter the asc parameter
	 * @param ignoreParameter the ignore parameter
	 * @return the flagged comments
	 */
	@PreAuthorize("hasRole('ROLE_ADMIN') || hasRole('ROLE_MOD')")
	@GetMapping("/flags/comments")
	public Page<Comment> getFlaggedComments(@RequestParam("page") Optional<Integer> pageParameter,
			@RequestParam("size") Optional<Integer> sizeParameter,
			@RequestParam("asc") Optional<Boolean> ascParameter,
			@RequestParam("ignore") Optional<List<String>> ignoreParameter) {
		if (sizeParameter.isPresent() && sizeParameter.get() > 100) {
			sizeParameter = Optional.of(100);
		}

		Page<Comment> comments = commentManager.fetchFlagged(pageParameter.orElse(0),
				sizeParameter.orElse(settingsManager.getPageSize()), ascParameter.orElse(false));
		List<String> ignore = ignoreParameter.orElse(Lists.newArrayList("flag", "unflag"));
		commentManager.applyMetadata(getCurrentUsername(), comments.getContent(), ignore);
		return comments;
	}

	/**
	 * Gets the flagged entries.
	 *
	 * @param pageParameter the page parameter
	 * @param sizeParameter the size parameter
	 * @param ascParameter the asc parameter
	 * @param ignoreParameter the ignore parameter
	 * @return the flagged entries
	 */
	@PreAuthorize("hasRole('ROLE_ADMIN') || hasRole('ROLE_MOD')")
	@GetMapping("/flags/entries")
	public Page<Entry> getFlaggedEntries(@RequestParam("page") Optional<Integer> pageParameter,
			@RequestParam("size") Optional<Integer> sizeParameter,
			@RequestParam("asc") Optional<Boolean> ascParameter,
			@RequestParam("ignore") Optional<List<String>> ignoreParameter) {
		if (sizeParameter.isPresent() && sizeParameter.get() > 100) {
			sizeParameter = Optional.of(100);
		}

		Page<Entry> entries = entryManager.fetchFlagged(pageParameter.orElse(0),
				sizeParameter.orElse(settingsManager.getPageSize()), ascParameter.orElse(false));
		List<String> ignore = ignoreParameter.orElse(Lists.newArrayList("flag", "unflag", "bookmark", "removeBookmark"));
		entryManager.applyMetadata(getCurrentUsername(), userManager.getKarma(getCurrentUsername()),
				entries.getContent(), ignore);
		return entries;
	}

	/**
	 * Unflag comment.
	 *
	 * @param id the id
	 */
	@PreAuthorize("hasRole('ROLE_ADMIN') || hasRole('ROLE_MOD')")
	@DeleteMapping("/flags/comment/{id}")
	public void unflagComment(@PathVariable("id") Long id) {
		if (!commentManager.exists(id)) {
			throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
		}

		flagManager.unflag(id, Types.comment);
	}

	/**
	 * Unflag entry.
	 *
	 * @param id the id
	 */
	@PreAuthorize("hasRole('ROLE_ADMIN') || hasRole('ROLE_MOD')")
	@DeleteMapping("/flags/entry/{id}")
	public void unflagEntry(@PathVariable("id") Long id) {
		if (!entryManager.exists(id)) {
			throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
		}

		flagManager.unflag(id, Types.entry);
	}

	/**
	 * Delete comment.
	 *
	 * @param id the id
	 */
	@PreAuthorize("hasRole('ROLE_ADMIN') || hasRole('ROLE_MOD')")
	@DeleteMapping("/comment/{id}")
	public void deleteComment(@PathVariable("id") Long id) {
		if (!commentManager.exists(id)) {
			throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
		}

		commentManager.delete(commentManager.get(id));
	}

	/**
	 * Delete entry.
	 *
	 * @param id the id
	 */
	@PreAuthorize("hasRole('ROLE_ADMIN') || hasRole('ROLE_MOD')")
	@DeleteMapping("/entry/{id}")
	public void deleteEntry(@PathVariable("id") Long id) {
		if (!entryManager.exists(id)) {
			throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
		}

		entryManager.delete(entryManager.get(id));
	}

	/**
	 * Make mod.
	 *
	 * @param username the username
	 */
	@PreAuthorize("hasRole('ROLE_ADMIN')")
	@PutMapping("/user/{username}")
	public void makeMod(@PathVariable("username") String username) {
		LocalUser user = userManager.getByUsername(username);

		if (user == null) {
			throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
		}

		if (user.getRoles() == null) {
			user.setRoles(Lists.newArrayList());
		}

		if (user.getRoles().contains("ROLE_MOD")) {
			throw new EntityResponseStatusException(HttpStatus.NO_CONTENT);
		}

		user.getRoles().add("ROLE_MOD");

		userManager.save(user);
	}

	/**
	 * Unmake mode.
	 *
	 * @param username the username
	 */
	@PreAuthorize("hasRole('ROLE_ADMIN')")
	@DeleteMapping("/user/{username}")
	public void unmakeMode(@PathVariable("username") String username) {
		LocalUser user = userManager.getByUsername(username);

		if (user == null) {
			throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
		}

		if (user.getRoles() == null) {
			user.setRoles(Lists.newArrayList());
		}

		if (!user.getRoles().contains("ROLE_MOD")) {
			throw new EntityResponseStatusException(HttpStatus.NO_CONTENT);
		}

		user.getRoles().remove("ROLE_MOD");

		userManager.save(user);
	}
}
