package cn.edu.tju.se.auth.web;

import java.security.Principal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import cn.edu.tju.se.auth.dao.UserRepository;
import cn.edu.tju.se.auth.domain.Role;
import cn.edu.tju.se.auth.domain.User;
import cn.edu.tju.se.auth.service.UserService;
import cn.edu.tju.se.base.domain.ErrorCode;
import cn.edu.tju.se.base.exception.MyException;
import cn.edu.tju.se.security.JwtAuthenticationRequest;
import cn.edu.tju.se.security.JwtAuthenticationResponse;

@RestController
@RequestMapping(value = "/api")
public class UserController {

	@Autowired
	UserDetailsService userDetailsService;
	@Autowired
	UserService userService;

	@RequestMapping("/user")
	public User getUser(Principal user) {
		return userService.findByUsername(user.getName());
	}

	// public User getUser(HttpServletRequest request,
	// HttpServletResponse response){
	// SecurityContextImpl sci = (SecurityContextImpl)
	// request.getSession().getAttribute(
	// "SPRING_SECURITY_CONTEXT");
	// return userService.findByUsername(sci.getAuthentication().getName());
	// }

	@PreAuthorize("hasRole('ADMIN')")
	@RequestMapping(value = "/users", method = RequestMethod.GET)
	public List<User> getUsers() {
		List<User> users = new ArrayList<User>();
		Iterator<User> it = userService.findAll().iterator();
		while (it.hasNext()) {
			users.add(it.next());
		}
		return users;
	}

	// @PreAuthorize("hasRole('ADMIN')")
	@RequestMapping(value = { "/users", "/public/users" }, method = RequestMethod.POST)
	User addUser(@RequestBody User user) {
		user.setId(null);
		user.setRoles(new HashSet<Role>());
		return userService.add(user);
	}

	@PostAuthorize("returnObject.username == principal.username or hasRole('ROLE_ADMIN')")
	@RequestMapping(value = "/users/{id}", method = RequestMethod.GET)
	public User getUser(@PathVariable Long id) {
		User user = userService.findOne(id);
		return user;
	}

	// @PostAuthorize("returnObject.username == principal.username or
	// hasRole('ROLE_ADMIN')")
	@RequestMapping(value = { "/users/username/{username}",
			"/public/users/username/{username}" }, method = RequestMethod.GET)
	public User getUserByUsername(@PathVariable String username) {
		User user = userService.findByUsername(username);
		if (user == null) {
			return null;
		} else {
			return user;
		}
	}

	@RequestMapping(value = { "/users/phone/{phone}", "/public/users/phone/{phone}" }, method = RequestMethod.GET)
	public Long getUserByPhone(@PathVariable String phone) {
		User user = userService.findByPhone(phone);
		if (user == null) {
			return null;
		} else {
			return user.getId();
		}
	}

	@RequestMapping(value = { "/users/email/{email}", "/public/users/email/{email}" }, method = RequestMethod.GET)
	public Long getUserByEmail(@PathVariable String email) {
		User user = userService.findByEmail(email);
		if (user == null) {
			return null;
		} else {
			return user.getId();
		}
	}

	//@PreAuthorize("hasRole('USER')")
	@RequestMapping(value = "/users/{id}", method = RequestMethod.PUT)
	User updateUser(@PathVariable Long id, @RequestBody User updatedUser, Principal user) {
		if (userService.findByUsername(user.getName()).getId() == id) {
			updatedUser.setId(id);
			return userService.update(updatedUser);
		} else {
			return null;
		}

	}

	@PreAuthorize("hasRole('USER')")
	@RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE)
	User removeUser(@PathVariable Long id, Principal user) {
		if (userService.findByUsername(user.getName()).getId() == id) {
			User deletedUser = userService.findOne(id);
			userService.delete(id);
			return deletedUser;
		} else {
			return null;
		}
	}

}
