package org.minager.account;

import java.io.IOException;
import java.util.Optional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.minager.core.entities.dto.PasswordWrapperDTO;
import org.minager.core.entities.dto.UserDTO;
import org.minager.core.entities.persistence.User;
import org.minager.core.security.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/account")
public class AccountController {

	private static final String HEADER_TOKEN = "token";
	
	@Autowired
	private AccountService accountService;
	
	@Autowired
	private TokenService tokenService;
	
	/**
	 * Log in the user in request body.
	 * 
	 * @param pUser
	 *            The user to connect.
	 * @param response
	 *            The reponse injected by Spring.
	 * @return The connected user object.
	 * @throws IOException
	 *             If credentials are bad.
	 */
	@PostMapping("/login")
	public UserDTO login(@RequestBody UserDTO pUser, HttpServletResponse response) throws IOException {
		return accountService.checkCredentials(response, pUser);
	}
	
	/**
	 * Log out the user.
	 * 
	 * @param pRequest
	 *            The request injected by Spring.
	 */
	@GetMapping("/logout")
	public void logout(HttpServletRequest pRequest) {
		tokenService.removeUser(pRequest.getHeader(HEADER_TOKEN));
	}
	
	/**
	 * Updates the user password.
	 * 
	 * @param pPasswordWrapper
	 *            The object which contains the old password for verification and
	 *            the new password to set to the user.
	 * @param pRequest
	 *            The request injected by Spring.
	 * @param pResponse
	 *            The reponse injected by Spring.
	 * @throws IOException
	 *             If the old password doesn't match to the user password in
	 *             database.
	 */
	@PutMapping("/changePassword")
	public void changePassword(@RequestBody final PasswordWrapperDTO pPasswordWrapper,
			final HttpServletRequest pRequest,
			final HttpServletResponse pResponse) throws IOException {
		final Optional<User> connectedUser = tokenService.getAuthenticatedUserByToken(pRequest);
		if(connectedUser.isPresent()) {
			accountService.changePassword(connectedUser.get(), pPasswordWrapper, pResponse);
		} else {
			pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
		}
	}
	
	@PostMapping("/signin")
	public UserDTO signin(@RequestBody final UserDTO pUser, final HttpServletResponse pResponse) throws IOException {
		return accountService.signin(pUser, pResponse);
	}
	
	@PutMapping("/")
	public void update(@RequestBody final UserDTO pUser, final HttpServletRequest pRequest,
			final HttpServletResponse pResponse) throws IOException {
		accountService.updateUser(pUser, pRequest, pResponse);
	}
}
