package eu.dnetlib.scholix.api.index;

import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;

/**
 * The type Elastic search client factory.
 */
public class ElasticSearchClientFactory implements PooledObjectFactory<Pair<RestHighLevelClient, ElasticsearchRestTemplate>> {

    private final ElasticSearchProperties elasticSearchProperties;


    /**
     * Instantiates a new Elastic search client factory.
     *
     * @param elasticSearchProperties the elastic search properties
     */
    public ElasticSearchClientFactory(final  ElasticSearchProperties elasticSearchProperties){
        this.elasticSearchProperties = elasticSearchProperties;

    }

    public PooledObject<Pair<RestHighLevelClient, ElasticsearchRestTemplate>> makeObject() throws Exception {

        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo(elasticSearchProperties.getClusterNodes().split(","))
                .withConnectTimeout(elasticSearchProperties.getConnectionTimeout())
                .withSocketTimeout(elasticSearchProperties.getSocketTimeout())
                .build();
        RestHighLevelClient cc = RestClients.create(clientConfiguration).rest();

        return new DefaultPooledObject<>(new ImmutablePair<>(cc, new ElasticsearchRestTemplate(cc)));
    }

    public void destroyObject(PooledObject<Pair<RestHighLevelClient, ElasticsearchRestTemplate>> pooledObject) throws Exception {
        RestHighLevelClient client = pooledObject.getObject().getLeft();
        if(client!=null&&client.ping(RequestOptions.DEFAULT)){
            try {
                client.close();
            }catch (Exception e){
                //ignore
            }
        }
    }

    public boolean validateObject(PooledObject<Pair<RestHighLevelClient, ElasticsearchRestTemplate>> pooledObject) {
        RestHighLevelClient client = pooledObject.getObject().getLeft();
        try {
            return client.ping(RequestOptions.DEFAULT);
        }catch(Exception e){
            return false;
        }
    }

    public void activateObject(PooledObject<Pair<RestHighLevelClient, ElasticsearchRestTemplate>> pooledObject) throws Exception {
        RestHighLevelClient client = pooledObject.getObject().getLeft();
        boolean response = client.ping(RequestOptions.DEFAULT);
    }

    public void passivateObject(PooledObject<Pair<RestHighLevelClient, ElasticsearchRestTemplate>> pooledObject) throws Exception {
        //nothing
    }


}