package org.codiki.images;

import org.codiki.core.entities.dto.ImageDTO;
import org.codiki.core.services.IllegalAccessException;
import org.codiki.core.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.Principal;
import java.util.Collections;
import java.util.List;
import java.util.NoSuchElementException;

@RestController
@RequestMapping("/api/images")
public class ImageController {
	private static final Logger LOG = LoggerFactory.getLogger(ImageController.class);
    /** Image service. */
	private ImageService imageService;

    /**
     * Constructor.
     * @param imageService Image service.
     */
    public ImageController(ImageService imageService) {
        this.imageService = imageService;
    }

    @PostMapping("/uploadAvatar")
	public ResponseEntity<String> uploadAvatar(@RequestParam("file") MultipartFile pFile,
                                               final Principal pPrincipal) {
		LOG.debug("Upload avatar.");
		ResponseEntity<String> result;
		try {
			result = ResponseEntity.ok(imageService.uploadAvatar(pFile, pPrincipal));
		} catch(IllegalAccessException ex) {
			result = ResponseEntity.status(HttpServletResponse.SC_UNAUTHORIZED).build();
		} catch(Exception ex) {
			LOG.error("Error during avatar upload.", ex);
			result = ResponseEntity.status(HttpServletResponse.SC_INTERNAL_SERVER_ERROR)
							.body(StringUtils.concat("Fail to upload ", pFile.getOriginalFilename() + "."));
		}
		return result;
	}
	
	@PostMapping
	public ResponseEntity<String> uploadImage(@RequestParam("file") MultipartFile pFile, final Principal pPrincipal) {
		ResponseEntity<String> result;
		try {
			result = ResponseEntity.status(HttpStatus.OK)
					.body(imageService.uploadImage(pFile,  pPrincipal));
		} catch(IllegalAccessException pEx) {
			result = ResponseEntity.status(HttpServletResponse.SC_UNAUTHORIZED).build();
		} catch(Exception ex) {
			result = ResponseEntity.status(HttpStatus.EXPECTATION_FAILED)
					.body(StringUtils.concat("Fail to upload ", pFile.getOriginalFilename() + "."));
		}
		return result;
	}
	
	@GetMapping("/loadAvatar/{avatarFileName}")
	public ResponseEntity<Resource> loadAvatar(@PathVariable("avatarFileName") final String pAvatarFileName) {
	    return imageService.loadAvatar(pAvatarFileName)
				.map(this::buildLoadImageResponse)
				.orElse(ResponseEntity.notFound().build());
	}
	
	@GetMapping("/{imageLink}")
	public ResponseEntity<Resource> loadImage(@PathVariable("imageLink") final String pImageLink) {
		return imageService.loadImage(pImageLink)
				.map(this::buildLoadImageResponse)
				.orElse(ResponseEntity.notFound().build());
	}
	
	private ResponseEntity<Resource> buildLoadImageResponse(final Resource pImageFile) {
		return ResponseEntity.ok()
				.header(HttpHeaders.CONTENT_DISPOSITION, StringUtils.concat("attachment; filename=\"", pImageFile.getFilename(), "\""))
				.body(pImageFile);
	}
	
	@GetMapping("/myImages")
	public List<ImageDTO> myImages(final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
		List<ImageDTO> result = Collections.emptyList();
		try {
			result = imageService.getUserImages(pPrincipal);
		} catch (NoSuchElementException ex) {
			pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
		}
		return result;
	}
	
	@GetMapping("/{imageLink}/details")
	public ResponseEntity<ImageDTO> getImageDetails(@PathVariable("imageLink") final String pImageLink)  {
        return ResponseEntity.of(imageService.getImageDetails(pImageLink));
	}
}
