package org.testcontainers.containers;

import org.influxdb.InfluxDB;
import org.influxdb.InfluxDBFactory;
import org.testcontainers.containers.traits.LinkableContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.containers.wait.strategy.WaitAllStrategy;

/**
 * @link https://store.docker.com/images/influxdb
 */
public class InfluxDBContainer<SELF extends InfluxDBContainer<SELF>> extends GenericContainer<SELF>
    implements LinkableContainer {

    public static final String VERSION = "1.4.3";
    public static final Integer INFLUXDB_PORT = 8086;

    private static final String IMAGE_NAME = "influxdb";

    private boolean authEnabled = true;
    private String admin = "admin";
    private String adminPassword = "password";

    private String database;
    private String username = "any";
    private String password = "any";


    public InfluxDBContainer() {
        this(VERSION);
    }

    public InfluxDBContainer(final String version) {
        super(IMAGE_NAME + ":" + version);
        waitStrategy = new WaitAllStrategy()
            .withStrategy(Wait.forHttp("/ping").withBasicCredentials(username, password).forStatusCode(204))
            .withStrategy(Wait.forListeningPort());
    }

    @Override
    protected void configure() {
        addExposedPort(INFLUXDB_PORT);

        addEnv("INFLUXDB_ADMIN_USER", admin);
        addEnv("INFLUXDB_ADMIN_PASSWORD", adminPassword);

        addEnv("INFLUXDB_HTTP_AUTH_ENABLED", String.valueOf(authEnabled));

        addEnv("INFLUXDB_DB", database);
        addEnv("INFLUXDB_USER", username);
        addEnv("INFLUXDB_USER_PASSWORD", password);
    }

    @Override
    protected Integer getLivenessCheckPort() {
        return getMappedPort(INFLUXDB_PORT);
    }


    /**
     * Set env variable `INFLUXDB_HTTP_AUTH_ENABLED`.
     *
     * @param authEnabled Enables authentication.
     * @return a reference to this container instance
     */
    public SELF withAuthEnabled(final boolean authEnabled) {
        this.authEnabled = authEnabled;
        return self();
    }

    /**
     * Set env variable `INFLUXDB_ADMIN_USER`.
     *
     * @param admin The name of the admin user to be created. If this is unset, no admin user is created.
     * @return a reference to this container instance
     */
    public SELF withAdmin(final String admin) {
        this.admin = admin;
        return self();
    }

    /**
     * Set env variable `INFLUXDB_ADMIN_PASSWORD`.
     *
     * @param adminPassword TThe password for the admin user configured with `INFLUXDB_ADMIN_USER`. If this is unset, a
     *                      random password is generated and printed to standard out.
     * @return a reference to this container instance
     */
    public SELF withAdminPassword(final String adminPassword) {
        this.adminPassword = adminPassword;
        return self();
    }

    /**
     * Set env variable `INFLUXDB_DB`.
     *
     * @param database Automatically initializes a database with the name of this environment variable.
     * @return a reference to this container instance
     */
    public SELF withDatabase(final String database) {
        this.database = database;
        return self();
    }

    /**
     * Set env variable `INFLUXDB_USER`.
     *
     * @param username The name of a user to be created with no privileges. If `INFLUXDB_DB` is set, this user will
     *                 be granted read and write permissions for that database.
     * @return a reference to this container instance
     */
    public SELF withUsername(final String username) {
        this.username = username;
        return self();
    }

    /**
     * Set env variable `INFLUXDB_USER_PASSWORD`.
     *
     * @param password The password for the user configured with `INFLUXDB_USER`. If this is unset, a random password
     *                 is generated and printed to standard out.
     * @return a reference to this container instance
     */
    public SELF withPassword(final String password) {
        this.password = password;
        return self();
    }


    /**
     * @return a url to influxDb
     */
    public String getUrl() {
        return "http://" + getContainerIpAddress() + ":" + getLivenessCheckPort();
    }

    /**
     * @return a influxDb client
     */
    public InfluxDB getNewInfluxDB() {
        InfluxDB influxDB = InfluxDBFactory.connect(getUrl(), username, password);
        influxDB.setDatabase(database);
        return influxDB;
    }
}

@@ -104,71 +104,8 @@
 ry;%0A
-import org.testcontainers.containers.traits.LinkableContainer;%0A
 impo
@@ -230,21 +230,123 @@
 y;%0A%0A
-/**%0A * @link 
+import java.util.Collections;%0Aimport java.util.Set;%0A%0A/**%0A * See %3Ca href=%22https://store.docker.com/images/influxdb%22%3E
 http
@@ -381,16 +381,20 @@
 influxdb
+%3C/a%3E
 %0A */%0Apub
@@ -493,41 +493,8 @@
 ELF%3E
-%0A    implements LinkableContainer
  %7B%0A%0A
@@ -1691,24 +1691,26 @@
    p
-rotected 
+ublic Set%3C
 Integer
+%3E
  get
@@ -1726,16 +1726,23 @@
 heckPort
+Numbers
 () %7B%0A   
@@ -1753,16 +1753,38 @@
  return 
+Collections.singleton(
 getMappe
@@ -1803,16 +1803,17 @@
 DB_PORT)
+)
 ;%0A    %7D%0A
@@ -1805,33 +1805,32 @@
 _PORT));%0A    %7D%0A%0A
-%0A
     /**%0A     * S

fix InfluxDBContainer's JavaDoc and remove deprecated APIs