package org.codiki.images;

import org.codiki.core.entities.dto.ImageDTO;
import org.codiki.core.entities.persistence.Image;
import org.codiki.core.entities.persistence.User;
import org.codiki.core.repositories.ImageRepository;
import org.codiki.core.repositories.UserRepository;
import org.codiki.core.services.FileUploadService;
import org.codiki.core.services.IllegalAccessException;
import org.codiki.core.services.UserService;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.security.Principal;
import java.util.Date;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class ImageService {
	/** User service. */
	private UserService userService;
	/** User repository. */
	private UserRepository userRepository;
	/** File upload service. */
	private FileUploadService fileUploadService;
	/** Image repository. */
	private ImageRepository imageRepository;

	/**
	 * Constructor.
	 * @param userService User service.
	 * @param userRepository User repository.
	 * @param fileUploadService File upload service.
	 * @param imageRepository Image repository.
	 */
	ImageService(UserService userService,
						UserRepository userRepository,
						FileUploadService fileUploadService,
						ImageRepository imageRepository) {
		this.userService = userService;
		this.userRepository = userRepository;
		this.fileUploadService = fileUploadService;
		this.imageRepository = imageRepository;
	}

	/**
	 * Save the uploaded file in persistence folder and set it as profil picture to uploader-user.
	 * @param pFile Uploaded file
	 * @param pPrincipal Uploader-user.
	 * @return Name of the uploaded file.
	 * @throws IllegalAccessException If the user isn't allowed to upload file
	 */
	public String uploadAvatar(final MultipartFile pFile,
							   final Principal pPrincipal) throws IllegalAccessException {
		final String avatarFileName = fileUploadService.uploadProfileImage(pFile);

		userService.getUserByPrincipal(pPrincipal)
				.ifPresentOrElse(user -> {
					user.setImage(avatarFileName);
					userRepository.save(user);
				}, IllegalAccessException::new);

		return avatarFileName;
	}
	
	public String uploadImage(final MultipartFile pFile, final Principal pPrincipal) {
		final String imageFileName = fileUploadService.uploadImage(pFile);

        userService.getUserByPrincipal(pPrincipal)
                .ifPresentOrElse(user -> {
                    final Image image = new Image();
                    image.setLink(imageFileName);
                    image.setDate(new Date());
                    image.setUser(user);
                    imageRepository.save(image);
                }, IllegalAccessException::new);

		return imageFileName;
	}
	
	public Optional<Resource> loadAvatar(final String pAvatarFileName) {
		return fileUploadService.loadAvatar(pAvatarFileName);
	}
	
	Optional<Resource> loadImage(final String pImageLink) {
		return fileUploadService.loadImage(pImageLink);
	}
	
	List<ImageDTO> getUserImages(final Principal pPrincipal) {
	    return imageRepository.getByUserId(userService.getUserByPrincipal(pPrincipal)
							.map(User::getId)
							.orElseThrow(NoSuchElementException::new))
				.stream()
				.map(ImageDTO::new)
				.collect(Collectors.toList());
	}

	public Optional<ImageDTO> getImageDetails(final String pImageLink) {
		return imageRepository.findByLink(pImageLink)
                .map(ImageDTO::new);
	}
}
