package org.codiki.core.services;

import org.apache.commons.lang.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;

@Service
public class FileUploadService {
	/** Logger. */
	private static final Logger LOG = LoggerFactory.getLogger(FileUploadService.class);
	/** Length of uploaded file names. */
	private static final int DESTINATION_IMAGE_NAME_LENGTH = 30;

	private final String folderUpload;
	private final String folderProfileImages;
	private final String folderImages;

	public FileUploadService(@Value("${codiki.files.upload}") String folderUpload,
							 @Value("${codiki.files.profile-images}") String folderProfileImages,
							 @Value("${codiki.files.images}")String folderImages) {
		this.folderUpload = folderUpload;
		this.folderProfileImages = folderProfileImages;
		this.folderImages = folderImages;
	}

	/**
	 * Builds the destination file name, which is a random string with 30 char
	 * length.
	 * 
	 * @return The file name.
	 */
	private String buildDestinationFileName() {
		return RandomStringUtils.randomAlphanumeric(DESTINATION_IMAGE_NAME_LENGTH);
	}
	
	public String uploadProfileImage(final MultipartFile pFile) {
		return uploadFile(pFile, folderProfileImages);
	}
	
	public String uploadImage(final MultipartFile pFile) {
		return uploadFile(pFile, folderImages);
	}
	
	private String uploadFile(final MultipartFile pFile, final String pPath) {
		String result;
		try {
			result = buildDestinationFileName();
			final Path destinationFile = Paths.get(pPath).resolve(result);
			LOG.debug("Upload file saved as {}", destinationFile.toString());
			Files.copy(pFile.getInputStream(), destinationFile);
			return result;
		} catch (final Exception pEx) {
			LOG.error("Error during file upload.", pEx);
			// TODO : Refactor exception
			throw new RuntimeException();
		}
	}

	public Optional<Resource> loadAvatar(final String pAvatarFileName) {
		Optional<Resource> result = Optional.empty();

		try {
			result = loadImage(pAvatarFileName, folderProfileImages);
		} catch(final IOException ex) {
			LOG.error("Unable to load avatar file {}", pAvatarFileName, ex);
		}

		return result;
	}
	
	public Optional<Resource> loadImage(final String pImageLink) {
		Optional<Resource> result = Optional.empty();

		try {
			result = loadImage(pImageLink, folderImages);
		} catch(final IOException ex) {
			LOG.error("Unable to load image file {}", pImageLink, ex);
		}

		return result;
	}

	private Optional<Resource> loadImage(final String pImageLink, final String pFilePath) throws IOException {
		Optional<Resource> result = Optional.empty();

		Path imageFile = Paths.get(pFilePath).resolve(pImageLink);
		Resource imageResource = new UrlResource(imageFile.toUri());
		if(imageResource.exists() || imageResource.isReadable()) {
			result = Optional.of(imageResource);
		} else {
			LOG.warn("Unknown file {}", imageFile);
		}

		return result;
	}
}
