package com.constellio.model.services.users;
import static java.util.Arrays.asList;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.constellio.data.dao.managers.config.ConfigManager;
import com.constellio.data.dao.managers.config.ConfigManagerException.OptimisticLockingConfiguration;
import com.constellio.data.dao.managers.config.values.BinaryConfiguration;
import com.constellio.data.dao.services.contents.ContentDao;
import com.constellio.data.dao.services.contents.ContentDaoException.ContentDaoException_NoSuchContent;
import com.constellio.data.dao.services.factories.DataLayerFactory;
import com.constellio.data.io.services.facades.IOServices;
import com.constellio.data.io.services.zip.ZipService;
import com.constellio.data.io.services.zip.ZipServiceException;
import com.constellio.data.io.streamFactories.StreamFactory;
import com.constellio.data.utils.ImpossibleRuntimeException;
import com.constellio.data.utils.TimeProvider;
import com.constellio.model.services.users.UserPhotosServicesRuntimeException.UserPhotosServicesRuntimeException_NoSuchUserLog;
import com.constellio.model.services.users.UserPhotosServicesRuntimeException.UserPhotosServicesRuntimeException_UserHasNoPhoto;
//AFTER : Rename UserFilesServices
public class UserPhotosServices {
public static final String DATE_PATTERN = "yyyy-MM-dd'T'HH_mm_ss.SSS";
private final String ZIP_LOG_FILE_RESOURCENAME = "UserFilesServices-zipLogFile";
private final String ZIP_LOG_TEMP_FOLDER_RESOURCENAME = "UserFilesServices-zipLogTempFolder";
private final String WRITE_LOG_FILE_TO_TEMP_FOLDER_RESOURCENAME = "UserFilesServices-writeLogFileToTempFolderOutputStream";
private final String READ_LOG_FILE_RESOURCENAME = "UserFilesServices-readLogFileInputStream";
private IOServices ioServices;
private ContentDao contentDao;
private ConfigManager configManager;
private ZipService zipService;
public UserPhotosServices(DataLayerFactory dataLayerFactory) {
this.configManager = dataLayerFactory.getConfigManager();
this.contentDao = dataLayerFactory.getContentsDao();
this.ioServices = dataLayerFactory.getIOServicesFactory().newIOServices();
this.zipService = dataLayerFactory.getIOServicesFactory().newZipService();
}
public void changePhoto(InputStream inputStream, String username) {
String configPath = getPhotoConfigPath(username);
if (configManager.exist(configPath)) {
String hash = configManager.getBinary(configPath).getHash();
try {
configManager.update(configPath, hash, inputStream);
} catch (OptimisticLockingConfiguration optimisticLockingConfiguration) {
throw new ImpossibleRuntimeException(optimisticLockingConfiguration);
}
} else {
configManager.add(configPath, inputStream);
}
}
public StreamFactory<InputStream> getPhotoInputStream(String username) {
String configPath = getPhotoConfigPath(username);
if (configManager.exist(configPath)) {
BinaryConfiguration binaryConfiguration = configManager.getBinary(configPath);
return binaryConfiguration.getInputStreamFactory();
} else {
throw new UserPhotosServicesRuntimeException_UserHasNoPhoto(username);
}
}
private String getPhotoConfigPath(String username) {
return "/photos/" + username;
}
public boolean hasPhoto(String username) {
String configPath = getPhotoConfigPath(username);
return configManager.exist(configPath);
}
private String getLogFolderId(String username) {
return "userlogs/" + username;
}
private String getLogId(String username, String log) {
return "userlogs/" + username + "/" + log;
}
public void addLogFile(String username, InputStream inputStream) {
String logName = TimeProvider.getLocalDateTime().toString(DATE_PATTERN);
addLogFile(username, logName, inputStream);
}
public void addLogFile(String username, String logName, InputStream inputStream) {
String path = getLogId(username, logName);
contentDao.add(path, inputStream);
}
public List<String> getUserLogs(String username) {
String folderId = getLogFolderId(username);
if (contentDao.isFolderExisting(folderId)) {
List<String> logs = new ArrayList<>();
for (String file : contentDao.getFolderContents(folderId)) {
logs.add(file.replace(folderId + "/", ""));
}
return logs;
} else {
return Collections.emptyList();
}
}
public InputStream newUserLogInputStream(String username, String log, String resourceName) {
String logPath = getLogId(username, log);
try {
return contentDao.getContentInputStream(logPath, resourceName);
} catch (ContentDaoException_NoSuchContent contentDaoException_noSuchContent) {
throw new UserPhotosServicesRuntimeException_NoSuchUserLog(username, log);
}
}
StreamFactory<InputStream> getAllLogs(final String username) {
return new StreamFactory<InputStream>() {
@Override
public InputStream create(String name)
throws IOException {
File zipFile = new File(ioServices.newTemporaryFolder(ZIP_LOG_FILE_RESOURCENAME), "logs.zip");
File tempFolder = ioServices.newTemporaryFolder(ZIP_LOG_TEMP_FOLDER_RESOURCENAME);
try {
copyUserLogFilesInTempFolder(tempFolder, username);
zipService.zip(zipFile, asList(tempFolder.listFiles()));
} catch (ZipServiceException | RuntimeException e) {
ioServices.deleteQuietly(zipFile);
throw new RuntimeException(e);
} finally {
ioServices.deleteQuietly(tempFolder);
}
return ioServices.newBufferedFileInputStreamWithFileDeleteOnClose(zipFile, name);
}
};
}
private void copyUserLogFilesInTempFolder(File tempFolder, String username)
throws IOException {
for (String log : getUserLogs(username)) {
File logFile = new File(tempFolder, log + ".zip");
OutputStream out = ioServices
.newBufferedFileOutputStream(logFile, WRITE_LOG_FILE_TO_TEMP_FOLDER_RESOURCENAME);
InputStream in;
try {
in = newUserLogInputStream(username, log, READ_LOG_FILE_RESOURCENAME);
} catch (RuntimeException e) {
ioServices.closeQuietly(out);
throw e;
}
ioServices.copyAndClose(in, out);
}
}
public void deleteUserLog(String username, String log) {
String logPath = getLogId(username, log);
contentDao.delete(asList(logPath));
}
}