/**
 * 
 */
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.ViewManager;
import de.bstly.board.controller.support.EntityResponseStatusException;
import de.bstly.board.controller.support.RequestBodyErrors;
import de.bstly.board.controller.validation.ViewValidator;
import de.bstly.board.model.View;

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

	@Autowired
	private ViewManager viewManager;
	@Autowired
	private SettingsManager settingsManager;
	@Autowired
	private ViewValidator viewValidator;

	/**
	 * 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<View> getViews(@RequestParam("page") Optional<Integer> pageParameter,
			@RequestParam("size") Optional<Integer> sizeParameter,
			@RequestParam("desc") Optional<Boolean> descParameter) {

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

		return viewManager.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<View> getPublicViews(@RequestParam("page") Optional<Integer> pageParameter,
			@RequestParam("size") Optional<Integer> sizeParameter,
			@RequestParam("desc") Optional<Boolean> descParameter) {
		return viewManager.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("/view/{name}")
	public View getView(@PathVariable("name") String name,
			@RequestParam("user") Optional<String> usernameParameter) {
		View view = viewManager.get(usernameParameter.orElse(getCurrentUsername()), name);

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

		return view;
	}

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

		RequestBodyErrors bindingResult = new RequestBodyErrors(view);
		viewValidator.validate(view, bindingResult);

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

		if (!viewManager.exists(getCurrentUsername(), view.getName())
				&& viewManager.countByUser(getCurrentUsername()) >= settingsManager.getMaxViews()) {
			throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
		}

		return viewManager.save(view);
	}

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

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

}
