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

import java.io.ByteArrayOutputStream;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
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.ServiceActivator;
import ru.bitel.bgbilling.kernel.admin.errorlog.server.AlarmSender;
import ru.bitel.bgbilling.modules.inet.common.bean.InetDevice;
import ru.bitel.bgbilling.modules.inet.common.bean.InetDeviceType;
import ru.bitel.bgbilling.server.util.Setup;
import ru.bitel.common.ParameterMap;
import ru.bitel.common.Utils;
import ru.bitel.common.io.IOUtils;

/**
 *  {@inheritDoc}
 *  @see AbstractTerminalServiceActivator
 */
public class ExecServiceActivator
	extends AbstractTerminalServiceActivator
	implements ServiceActivator
{
	private static final Logger logger = LogManager.getLogger();

	@Override
	public Object init( Setup setup, int moduleId, InetDevice device, InetDeviceType deviceType, ParameterMap config )
		throws Exception
	{
		super.init( setup, moduleId, device, deviceType, config );

		return null;
	}

	@Override
	public Object destroy()
		throws Exception
	{
		return super.destroy();
	}

	@Override
	public Object connect()
		throws Exception
	{
		return connectImpl();
	}

	protected Object connectImpl()
		throws Exception
	{
		if ( connectionSemaphore != null )
		{
			connectionSemaphoreAcquired = connectionSemaphore.tryAcquire( 3, TimeUnit.MINUTES );
		}

		return super.connect();
	}

	@Override
	public Object disconnect()
		throws Exception
	{
		if ( connectionSemaphore != null && connectionSemaphoreAcquired )
		{
			connectionSemaphore.release();
		}

		return null;
	}

	private static Pattern returnCodePattern = Pattern.compile( "RETURN_CODE=(\\d+)" );

	@Override
	protected void executeCommand( String command )
		throws Exception
	{
		logger.info( "[" + device + "] execute: " + command );

		Process process = Runtime.getRuntime().exec( command );

		if ( !process.waitFor( 1, TimeUnit.MINUTES ) )
		{
			throw new TimeoutException( "Timeout waiting when executing command." );
		}

		final ByteArrayOutputStream baos = new ByteArrayOutputStream();

		IOUtils.transfer( process.getInputStream(), baos, 256 );
		IOUtils.transfer( process.getErrorStream(), baos, 256 );

		byte[] resultBytes = baos.toByteArray();

		String result = new String( resultBytes, "UTF-8" );

		logger.info( result );

		if ( Utils.notBlankString( result ) )
		{
			Matcher m = returnCodePattern.matcher( result );
			while( m.find() )
			{
				String returnCode = m.group( 1 );

				if ( Utils.parseInt( returnCode, 0 ) == 0 )
				{
					continue;
				}

				logger.error( "Command \"" + command + "\" executed with RETURN_CODE=" + returnCode );

				String key = "inet.sa.ssh.returnCode";

					String subject = "Inet: Ошибка работы обработчика активации сервисов [" + deviceId + "] " + device.getGuiTitle();
					String message = "Ошибка работы обработчика активации сервисов [" + deviceId + "] " + device.getGuiTitle()
									 + "\n" + device.getHost()
									 + "\n(" + device.getComment() + ")\n\n"
									 + "Исполнение команды \"" + command + "\" завершилось с ошибкой " + returnCode + "!";

					AlarmSender.sendAlarm( key, 600000, subject, message );
			}
		}
	}
}
