package dst.ass1.doc;

import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;

import org.junit.rules.ExternalResource;

import de.flapdoodle.embed.mongo.config.IMongodConfig;
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
import de.flapdoodle.embed.mongo.config.Net;
import de.flapdoodle.embed.mongo.distribution.IFeatureAwareVersion;
import de.flapdoodle.embed.mongo.distribution.Version;
import de.flapdoodle.embed.mongo.tests.MongodForTestsFactory;

/**
 * JUnit rule that creates an in-memory instance of MongoDB using the flapdoodle Embedded MongoDB.
 */
public class EmbeddedMongo extends ExternalResource {

    private MongodForTestsFactory mongod;

    @Override
    protected void before() throws Throwable {
        requirePort();
        mongod = new MongodFactory(); // starts process in constructor
    }

    @Override
    protected void after() {
        if (mongod != null) {
            mongod.shutdown();
        }
    }

    private void requirePort() throws IOException, IllegalStateException {
        try (ServerSocket ignore = new ServerSocket(27017)) {
            // ignore
        } catch (BindException e) {
            throw new IllegalStateException("Could not bind port 27017 which is necessary to run the MongoDB tests", e);
        }
    }

    public static class MongodFactory extends MongodForTestsFactory {

        public MongodFactory() throws IOException {
            super(Version.Main.V3_5);
        }

        @Override
        protected IMongodConfig newMongodConfig(IFeatureAwareVersion version) throws IOException {
            return new MongodConfigBuilder()
                    .net(new Net(27017, false))
                    .version(version)
                    .build();
        }
    }
}
