package br.ufrgs.inf.prosoft.tigris.monitoring.storage;

import br.ufrgs.inf.prosoft.tigris.configuration.types.RepositoryType;
import br.ufrgs.inf.prosoft.tigris.exceptions.StorageException;
import br.ufrgs.inf.prosoft.tigris.monitoring.metadata.LogTrace;
import br.ufrgs.inf.prosoft.tigris.monitoring.storage.providers.AsyncFileRepository;
import br.ufrgs.inf.prosoft.tigris.monitoring.storage.providers.ConsoleRepository;
import br.ufrgs.inf.prosoft.tigris.monitoring.storage.providers.MemoryRepository;
import br.ufrgs.inf.prosoft.tigris.monitoring.storage.providers.MongoRepository;
import br.ufrgs.inf.prosoft.tigris.monitoring.storage.providers.RedisRepository;
import com.mongodb.MongoClient;
import com.mongodb.MongoTimeoutException;
import com.mongodb.client.MongoDatabase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.Properties;

/**
 * The type Repository factory.
 */
public class RepositoryFactory {

    /**
     * The Logger.
     */
    static Logger logger = LoggerFactory.getLogger(RepositoryFactory.class);

    /**
     * Gets repository.
     *
     * @param properties     the properties
     * @param repositoryType the repository type
     * @return the repository
     * @throws IOException the io exception
     */
    public static Repository getRepository(Properties properties, RepositoryType repositoryType) throws IOException {

        switch (repositoryType) {
            case MONGODB:
                try {
                    MongoClient mongo = new MongoClient(properties.getProperty("adaptivecaching.monitoring.db.address"), Integer.parseInt(properties.getProperty("adaptivecaching.monitoring.db.port")));
                    MongoDatabase database = mongo.getDatabase(properties.getProperty("adaptivecaching.monitoring.db.scheme"));
                    Repository repository = new MongoRepository<>(database.getCollection(properties.getProperty("adaptivecaching.monitoring.db.name")), LogTrace.class);
                    logger.debug("Repository created to MongoDB: " + repository.toString());
                    return repository;
                } catch (MongoTimeoutException e) {
                    throw new StorageException("Cannot connect with MongoDB with the defined properties.", e);
                }
            case REDIS:
                logger.debug("Repository is configured to Redis.");
                return new RedisRepository<LogTrace>();
            case TEXTFILE:
                AsyncFileRepository as = new AsyncFileRepository(new File("traces.txt"));
                as.open();
                logger.debug("Repository is configured to save logs in textfile.");
                return as;
            case MEMORY:
                logger.warn("Repository is configured to save logs in Memory, which is not recommended because it can take too much from the application.");
                return new MemoryRepository<LogTrace>();
            case CONSOLE:
                logger.warn("Repository is configured to just show logs in console. Nothing will be recorded");
                return new ConsoleRepository<LogTrace>();
            default:
                throw new StorageException("The specified repository type [" + repositoryType +"] does not have an available implementation.");
        }
    }
}
