package com.wx.application.nebula.graph.factory;

import java.util.Arrays;
import java.util.List;

import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;

import com.vesoft.nebula.client.graph.NebulaPoolConfig;
import com.vesoft.nebula.client.graph.data.HostAddress;
import com.vesoft.nebula.client.graph.net.NebulaPool;
import com.vesoft.nebula.client.graph.net.Session;

import lombok.extern.slf4j.Slf4j;

/**
 * Session工厂类，通过Session工厂提供Session实例的创建和销毁
 */
@Slf4j
public class SessionFactory extends BasePooledObjectFactory<Session> {

	NebulaPool pool;
	NebulaSessionProperties properties;
	
	public SessionFactory(NebulaSessionProperties properties) {
		
		NebulaPool pool = new NebulaPool();
	    NebulaPoolConfig nebulaPoolConfig = new NebulaPoolConfig();
	    nebulaPoolConfig.setMaxConnSize(100);
	    List<HostAddress> addresses = Arrays.asList(
	    		new HostAddress(properties.getHost(), properties.getPort()));
	    try {
			pool.init(addresses, nebulaPoolConfig);
		} catch (Exception e) {
			log.info("{}", e);
		} 
	    
		this.properties = properties;
		
		this.pool = pool;
	}
	
    /**
     * 创建对象
     */
    @Override
    public Session create() {
        Session session = null;
        try {
		    session = pool.getSession(properties.getUsername(), properties.getPassword(), false);
		} catch (Exception e) {
			log.info("{}",e);
		}
        return session;
    }

    /**
     * 用PooledObject封装对象放入池中
     */
    @Override
    public PooledObject<Session> wrap(Session session) {
        return new DefaultPooledObject<>(session);
    }

    /**
     * 销毁对象
     */
    @Override
    public void destroyObject(PooledObject<Session> sessionPooled) {
        if (sessionPooled == null) {
            return;
        }
        try {
            Session session = sessionPooled.getObject();
            session.release();
        } catch (Exception e) {
            log.error("failed to release session: {}", e);
        }
    }

    /**
     * 验证对象
     */
    @Override
    public boolean validateObject(PooledObject<Session> sessionPooled) {
    	if (sessionPooled == null) {
            return false;
        }
        try {
            Session session = sessionPooled.getObject();
            return session.ping();
        } catch (Exception e) {
            log.error("failed to validate session: {}", e);
        }
        return false;
    }
}
