package com.example.controller;

import com.example.entity.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

@RestController
public class UserController {
    @Autowired
    private UserService service;

    @PostMapping(value = "/users", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}, produces = "application/json")
    public ResponseEntity saveUsers(@RequestParam(value = "files") MultipartFile[] files) throws Exception {
        for (MultipartFile file : files) {
            service.saveUsers(file);
        }
        return ResponseEntity.status(HttpStatus.CREATED).build();
    }

    // save and get users
    @GetMapping(value = "/users", produces = "application/json")
    public List<User> findAllUsers() throws ExecutionException, InterruptedException {
        List<CompletableFuture<User>> userList = new ArrayList<>();
        for (int i = 1; i <= 20; i++) {
            service.saveUserById(i);
            CompletableFuture<User> user = service.getUserById(i);
            userList.add(user);
        }
        List<User> myUsers = new ArrayList<>();
        for (CompletableFuture<User> u: userList) {
            myUsers.add(u.get());
        }
        return myUsers;
    }

    // save and get users with different for loops
    @GetMapping(value = "/different", produces = "application/json")
    public List<User> findAllUsersEach() throws ExecutionException, InterruptedException, TimeoutException {
        List<CompletableFuture<User>> userList = new ArrayList<>();
        for (int i = 1; i <= 200; i++) {
            service.saveUserById(i);
//            CompletableFuture<User> user = service.getUserById(i);
//            userList.add(user);
        }
        for (int i = 1; i <= 200; i++) {
//            service.saveUserById(i);
            CompletableFuture<User> user = service.getUserById(i);
            userList.add(user);
        }

        List<User> myUsers = new ArrayList<>();
        // loops through entire list, waits if the task is incomplete.
        userList.forEach(CompletableFuture::join);
        for (CompletableFuture<User> u: userList) {
            // waits for 10 ms if the task is incomplete. Gets the result immediately if the task is already complete.
//            myUsers.add(u.get(10, TimeUnit.MILLISECONDS));
            myUsers.add(u.get());
        }
        return myUsers;
    }
    @GetMapping("/get")
    public List<User> getUsersAsync() throws ExecutionException, InterruptedException {
        List<CompletableFuture<User>> userList = new ArrayList<>();
        for (int i = 1; i <= 1000; i++) {
            CompletableFuture<User> user = service.findUserById(i);
            userList.add(user);
        }
        List<User> myUsers = new ArrayList<>();
        for (CompletableFuture<User> u: userList) {
            myUsers.add(u.get());
        }
        return myUsers;
    }
}