package ru.bitel.bgbilling.modules.inet.dyn.device.mikrotik;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import ru.bitel.bgbilling.apps.inet.access.sa.ServiceActivatorEvent;
import ru.bitel.bgbilling.common.model.ConfigParameter;
import ru.bitel.bgbilling.kernel.network.mikrotik.MikrotikApiSession;
import ru.bitel.bgbilling.modules.inet.common.bean.InetConnection;
import ru.bitel.bgbilling.modules.inet.common.bean.InetDevice;
import ru.bitel.bgbilling.modules.inet.common.bean.InetDeviceType;
import ru.bitel.bgbilling.modules.inet.common.bean.InetServ;
import ru.bitel.bgbilling.modules.inet.dyn.device.terminal.AbstractTerminalServiceActivator;
import ru.bitel.bgbilling.server.util.Setup;
import ru.bitel.common.ParameterMap;
import ru.bitel.common.Utils;

public class MikrotikServiceActivator
    extends AbstractTerminalServiceActivator
{
	private MikrotikApiSession session;
	private static final Logger logger = LogManager.getLogger();
	private Pattern resultPattern = Pattern.compile( "=(.+?)=(.+)" );
	private static final String RESULT_ID_PARAM = ".id";
	private String prevIdList = null;
	private String sourceHost = null;
	private int sourcePort = 0; 
	
	@Override
    public Object init( Setup setup, int moduleId, InetDevice device, InetDeviceType deviceType, ParameterMap config )
        throws Exception
    {	    
	    this.sourceHost = config.get( SA_SOURCE_HOST, null );
        this.sourcePort = config.getInt( SA_SOURCE_PORT, 0 );

	    return super.init( setup, moduleId, device, deviceType, config );
    }

	@Override
    public Object connect()
        throws Exception
    {
		session = new MikrotikApiSession( host, port, username, password, sourceHost, sourcePort );
		session.connect();
		return null;
    }

	@Override
    public Object disconnect()
        throws Exception
    {
	    super.disconnect();	    
	    // ничего не надо  запускать . на "/quit" приходит ответ c ошибкой !fatal. А у кого-то просто висло на "exit" 
	    //session.doCommand( this.exitCommand );
	    session.disconnect();
	    logger.debug( "Disconnected" );
	    return null;
    }
	
	
	protected String executeCommandMikrotik( String command )
	    throws Exception
	{
		logger.info( "execute: " + command );	
		command = command.replace( "\\n", "\n" );		
		String result = session.doCommand( command );
		logger.info( "result=" + result );
		return result;
	}
	
	@Override
	protected Object getValue( ServiceActivatorEvent e, InetServ serv, InetConnection connection, Set<Integer> options, String macros, Object[] args, Object[] globalArgs )
	    throws Exception
	{			
		if ( "servId".equals( macros ) )
		{
			return String.valueOf( serv.getId() );		
		}	
		if ( "prevIdList".equals( macros ) )
		{
			return prevIdList;
		}
		else
		{
			return super.getValue( e, serv, connection, options, macros, args, globalArgs );
		}
	}
	
	@Override
	protected Object executeCommands( ServiceActivatorEvent e, InetServ serv, InetConnection connection, Set<Integer> options, String[] commands )
    throws Exception
    {
    	if ( commands == null )
    	{
    		return null;
    	}
    
    	if ( this.workingOptions != null )
    	{
    		options = new HashSet<Integer>( options );
    		options.retainAll( this.workingOptions );
    	}
 
    	
    	for ( String command : commands )
    	{
    		command = this.macrosFormat.format( command, e, serv, connection, options );
    		
    		if ( Utils.notBlankString( command ) )
    		{
    			parseResultParamas( executeCommandMikrotik( command.trim() ) );    			
    		}
    	}
    
    	return null;
    }

	@Override
	protected void executeCommand( String command )
		throws Exception
	{
		//ничего не делаем все делают в executeCommandMikrotik		
	}	
	
	
	private void parseResultParamas( String command )
	{
		Matcher matcher =  resultPattern.matcher( command );
		
		prevIdList = "";
		while( matcher.find() )
		{
			String key = matcher.group( 1 );
			String value = matcher.group( 2 );
			if ( key != null && key.equals( RESULT_ID_PARAM ) )
			{
				if ( !Utils.isEmptyString( prevIdList ) )
				{
					prevIdList += ",";
				}
				prevIdList += value;
			}
		}
	}
	
    @Override
    public List<ConfigParameter> configParameterList()
    {
        List<ConfigParameter> configParameters = super.configParameterList();
        configParameters.add( new ConfigParameter( SA_SOURCE_HOST, "" ) );
        configParameters.add( new ConfigParameter( SA_SOURCE_PORT, "" ) );
        return configParameters;
    }
}