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

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.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import de.bstly.board.businesslogic.SettingsManager;
import de.bstly.board.businesslogic.UserPageManager;
import de.bstly.board.controller.support.EntityResponseStatusException;
import de.bstly.board.controller.support.RequestBodyErrors;
import de.bstly.board.controller.validation.UserPageValidator;
import de.bstly.board.model.UserPage;

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

	@Autowired
	private UserPageManager userPageManager;
	@Autowired
	private SettingsManager settingsManager;
	@Autowired
	private UserPageValidator userPageValidator;

	/**
	 * Gets the user pages.
	 *
	 * @param pageParameter the page parameter
	 * @param sizeParameter the size parameter
	 * @param descParameter the desc parameter
	 * @return the user pages
	 */
	@PreAuthorize("isAuthenticated()")
	@GetMapping()
	public Page<UserPage> getUserPages(@RequestParam("page") Optional<Integer> pageParameter,
			@RequestParam("size") Optional<Integer> sizeParameter,
			@RequestParam("desc") Optional<Boolean> descParameter) {

		if (userPageManager.countByUser(getCurrentUsername()) == 0L) {
			userPageManager.createDefault(getCurrentUsername());
		}

		return userPageManager.getByUser(getCurrentUsername(), pageParameter.orElse(0),
				sizeParameter.orElse(settingsManager.getPageSize()), descParameter.orElse(false));
	}

	/**
	 * Gets the public user pages.
	 *
	 * @param pageParameter the page parameter
	 * @param sizeParameter the size parameter
	 * @param descParameter the desc parameter
	 * @return the public user pages
	 */
	@PreAuthorize("isAuthenticated()")
	@GetMapping("/public")
	public Page<UserPage> getPublicUserPages(@RequestParam("page") Optional<Integer> pageParameter,
			@RequestParam("size") Optional<Integer> sizeParameter,
			@RequestParam("desc") Optional<Boolean> descParameter) {
		return userPageManager.getPublic(getCurrentUsername(), pageParameter.orElse(0),
				sizeParameter.orElse(settingsManager.getPageSize()), "name",
				descParameter.orElse(false));
	}

	/**
	 * Gets the user page.
	 *
	 * @param name the name
	 * @return the user page
	 */
	@PreAuthorize("isAuthenticated()")
	@GetMapping("/userpage/{name}")
	public UserPage getUserPage(@PathVariable("name") String name,
			@RequestParam("user") Optional<String> usernameParameter) {
		UserPage userPage = userPageManager.get(usernameParameter.orElse(getCurrentUsername()),
				name);

		if (userPage == null || usernameParameter.isPresent() && !userPage.isPublicPage()) {
			throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
		}

		return userPage;
	}

	/**
	 * Creates the or update.
	 *
	 * @param userPage the user page
	 * @return the user page
	 */
	@PreAuthorize("isAuthenticated()")
	@PostMapping("/userpage")
	public UserPage createOrUpdate(@RequestBody UserPage userPage) {
		userPage.setUsername(getCurrentUsername());

		RequestBodyErrors bindingResult = new RequestBodyErrors(userPage);
		userPageValidator.validate(userPage, bindingResult);

		if (bindingResult.hasErrors()) {
			throw new EntityResponseStatusException(bindingResult.getAllErrors(),
					HttpStatus.UNPROCESSABLE_ENTITY);
		}

		if (!userPageManager.exists(getCurrentUsername(), userPage.getName()) && userPageManager
				.countByUser(getCurrentUsername()) >= settingsManager.getMaxUserPages()) {
			throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
		}

		return userPageManager.save(userPage);
	}

	/**
	 * Delete user page.
	 *
	 * @param name the name
	 */
	@PreAuthorize("isAuthenticated()")
	@DeleteMapping("/userpage/{name}")
	public void deleteUserPage(@PathVariable("name") String name) {
		if (!userPageManager.exists(getCurrentUsername(), name)) {
			throw new EntityResponseStatusException(HttpStatus.FORBIDDEN);
		}

		userPageManager.delete(getCurrentUsername(), name);
	}

}
