package com.aemreunal.controller.user;

import net.minidev.json.JSONObject;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponentsBuilder;
import com.aemreunal.config.GlobalSettings;
import com.aemreunal.domain.User;
import com.aemreunal.exception.user.UsernameClashException;
import com.aemreunal.service.UserService;

/*
 ***************************
 * Copyright (c) 2014      *
 *                         *
 * This code belongs to:   *
 *                         *
 * @author Ahmet Emre Ünal *
 * S001974                 *
 *                         *
 * aemreunal@gmail.com     *
 * emre.unal@ozu.edu.tr    *
 *                         *
 * aemreunal.com           *
 ***************************
 */

@Controller
@RequestMapping(GlobalSettings.USER_PATH_MAPPING)
public class UserController {
    @Autowired
    private UserService userService;

    /**
     * Get the user with the specified username
     *
     * @param username
     *     The username of the user
     *
     * @return The user
     */
    // TODO require authentication to get details
    @RequestMapping(method = RequestMethod.GET,
                    value = GlobalSettings.USER_USERNAME_MAPPING,
                    produces = "application/json; charset=UTF-8")
    public ResponseEntity<User> getUserByUsername(@PathVariable String username) {
        User user = userService.findByUsername(username);
        return new ResponseEntity<User>(user, HttpStatus.OK);
    }

    /**
     * Create a new user
     *
     * @param userJson
     *     The user as a JSON object
     * @param builder
     *     The URI builder for post-creation redirect
     *
     * @return The created project
     *
     * @throws UsernameClashException
     */
    @RequestMapping(method = RequestMethod.POST, value = GlobalSettings.USER_CREATE_MAPPING, produces = "application/json; charset=UTF-8")
    public ResponseEntity<User> createUser(
        @RequestBody JSONObject userJson,
        UriComponentsBuilder builder) throws UsernameClashException {
        User savedUser = new User(userJson);
        savedUser = userService.save(savedUser);
        if (GlobalSettings.DEBUGGING) {
            System.out.println("Saved user with username = \'" + savedUser.getUsername() + "\' ID = \'" + savedUser.getUserId() + "\'");
        }
        return buildCreateResponse(builder, savedUser);
    }

    private ResponseEntity<User> buildCreateResponse(UriComponentsBuilder builder, User savedUser) {
        HttpHeaders headers = new HttpHeaders();
        headers.setLocation(builder.path(GlobalSettings.USER_SPECIFIC_MAPPING)
                                   .buildAndExpand(
                                       savedUser.getUsername())
                                   .toUri());
        return new ResponseEntity<User>(savedUser, headers, HttpStatus.CREATED);
    }

    /**
     * Delete the specified user, along with all the projects belonging to user.
     * <p/>
     * To delete the user, confirmation must be supplied as a URI parameter, in the form
     * of "?confirm=yes". If not supplied, the user will not be deleted.
     *
     * @param username
     *     The username of the user to delete
     * @param confirmation
     *     The confirmation parameter
     *
     * @return The status of the deletion action
     */
    /*
        TODO Instead of getting password via a parameter, just authenticate user with oauth:
        Define: "/user/XXX has access to everyting beyond XXX/... if it authenticates with the
        credentials of XXX" -> variable authentication.
        @RequestParam(value = "password", required = true) String password
     */
    @RequestMapping(method = RequestMethod.DELETE, value = GlobalSettings.USER_USERNAME_MAPPING)
    public ResponseEntity<User> deleteUser(
        @PathVariable String username,
        @RequestParam(value = "confirm", required = true) String confirmation) {
        if (confirmation.toLowerCase().equals("yes")) {
            User user = userService.delete(username);
            return new ResponseEntity<User>(user, HttpStatus.OK);
        } else {
            return new ResponseEntity<User>(HttpStatus.PRECONDITION_FAILED);
        }
    }
}

@@ -502,24 +502,82 @@
 omain.User;%0A
+import com.aemreunal.exception.MalformedRequestException;%0A
 import com.a
@@ -1830,32 +1830,181 @@
 new user%0A     *%0A
+     * User creation request JSON:%3Cbr/%3E%0A     * %7B%3Cbr/%3E%0A     *     %22username%22:%22testuser12%22,%3Cbr/%3E%0A     *     %22password%22:%22test_password%22%0A     * %7D%0A     *%0A
      * @param us
@@ -2514,44 +2514,66 @@
 tion
- %7B%0A        User savedUser = new User
+, MalformedRequestException %7B%0A        verifyUserCreateJson
 (use
@@ -2580,32 +2580,37 @@
 rJson);%0A        
+User 
 savedUser = user
@@ -2622,25 +2622,34 @@
 ce.save(
-savedUser
+new User(userJson)
 );%0A     
@@ -2889,24 +2889,309 @@
 er);%0A    %7D%0A%0A
+    // TODO verify JSON inputs%0A    private void verifyUserCreateJson(JSONObject userJson) throws MalformedRequestException %7B%0A        if (!userJson.containsKey(%22username%22) %7C%7C !userJson.containsKey(%22password%22)) %7B%0A            throw new MalformedRequestException(%22user%22);%0A        %7D%0A    %7D%0A%0A
     private 

Verify user create JSON