/*
 * Copyright (C) 2016/2022 Litote
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.litote.kmongo

import com.mongodb.ConnectionString
import de.flapdoodle.embed.mongo.MongodProcess
import de.flapdoodle.embed.mongo.MongodStarter
import de.flapdoodle.embed.mongo.config.MongodConfig
import de.flapdoodle.embed.mongo.config.Net
import de.flapdoodle.embed.mongo.distribution.IFeatureAwareVersion
import de.flapdoodle.embed.process.runtime.Network
import org.bson.BsonDocument
import org.bson.Document

/**
 *
 */
internal class StandaloneEmbeddedMongo(version: IFeatureAwareVersion) {

    var port = Network.getFreeServerPort()
    var config: MongodConfig = MongodConfig.builder()
        .version(version)
        .net(Net(port, Network.localhostIsIPv6()))
        .build()

    val mongodProcess: MongodProcess by lazy {
        createInstance()
    }

    fun connectionString(commandExecutor: (String, BsonDocument, (Document?, Throwable?) -> Unit) -> Unit): ConnectionString =
        ConnectionString(
            "mongodb://${mongodProcess.host}"
        )

    private fun createInstance(): MongodProcess {
        return MongodStarter.getInstance(EmbeddedMongoLog.embeddedConfig).prepare(config).let { executable ->
            Runtime.getRuntime().addShutdownHook(object : Thread() {
                override fun run() {
                    executable.stop()
                }
            })
            executable.start()
        }
    }
}