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

import java.util.LinkedHashMap;
import java.util.Map;

import ru.bitel.bgbilling.kernel.contract.api.common.util.MACParser;
import ru.bitel.bgbilling.kernel.network.snmp.SnmpClient;
import ru.bitel.bgbilling.modules.inet.common.bean.InetServ;
import ru.bitel.bgbilling.modules.inet.common.event.manage.InetDeviceManageEvent;
import ru.bitel.common.inet.IpAddress;
import ru.bitel.oss.systems.inventory.resource.common.DeviceManagerMethodType;
import ru.bitel.oss.systems.inventory.resource.server.DeviceManagerMethod;

/**
 * Обработчик управления устройством для коммутаторов Cisco с дополнительным набором команд, 
 * которые доступны в контекстном меню для устройства или сервиса договора.
 *  
 * @author amir
 */
public class CiscoSwitchDeviceManager
	extends TerminalDeviceManager
{
	private String sendCommand( String command )
		throws Exception
	{
		return command + ":\n" + getTerminalSession().sendCommand( command );
	}

	@DeviceManagerMethod(title = "Показать подписи на портах", types = { DeviceManagerMethodType.DEVICE })
	public Object showInterfacesDesciption()
		throws Exception
	{
		return sendCommand( "show interfaces description" );
	}

	@DeviceManagerMethod(title = "Посмотреть счетчики(ошибки) на порту", types = { DeviceManagerMethodType.ACCOUNT })
	public Object showInterfacesCountersE( final InetDeviceManageEvent e )
		throws Exception
	{
		final InetServ serv = getInetServ( e );

		return sendCommand( "show interfaces counters ethernet e" + serv.getInterfaceId() );
	}

	@DeviceManagerMethod(title = "Посмотреть счетчики(ошибки) на порту (2)", types = { DeviceManagerMethodType.ACCOUNT })
	public Object showInterfacesCountersFa( final InetDeviceManageEvent e )
		throws Exception
	{
		final InetServ serv = getInetServ( e );

		return sendCommand( "show interfaces counters fa1/0/" + serv.getInterfaceId() );
	}

	@DeviceManagerMethod(title = "MAC-адреса на VLAN", types = { DeviceManagerMethodType.ACCOUNT })
	public Object showMacsByVlan( final InetDeviceManageEvent e )
		throws Exception
	{
		final InetServ serv = getInetServ( e );

		return sendCommand( "sh br a vlan " + serv.getVlan() );
	}

	private byte[] extractMacAddress( final long[] oid )
	{
		byte[] result = new byte[6];

		for ( int i = 5; i >= 0; i-- )
		{
			result[i] = (byte)(oid[oid.length - 6 + i] & 0xff);
		}

		return result;
	}

	@DeviceManagerMethod(title = "Таблица DHCP snooping", types = { DeviceManagerMethodType.DEVICE })
	public Object rlIpDhcpSnoopTable( final InetDeviceManageEvent e )
		throws Exception
	{
		Map<IpAddress, String[]> result = new LinkedHashMap<>();

		snmpClient.walk( SnmpClient.oidFromString( "1.3.6.1.4.1.89.112.1.11.1.5" ), byte[].class, ( oid, value ) -> {

			byte[] macAddress = extractMacAddress( oid );
			IpAddress macAddressObj = new IpAddress( macAddress );

			String[] data = result.computeIfAbsent( macAddressObj, ( k ) -> new String[5] );

			data[0] = IpAddress.toString( value );
			data[3] = String.valueOf( oid[oid.length - 7] );
		} );

		snmpClient.walk( SnmpClient.oidFromString( "1.3.6.1.4.1.89.112.1.11.1.6" ), String.class, ( oid, value ) -> {

			byte[] macAddress = extractMacAddress( oid );
			IpAddress macAddressObj = new IpAddress( macAddress );

			String[] data = result.computeIfAbsent( macAddressObj, ( k ) -> new String[5] );

			data[4] = "e" + value;
		} );

		snmpClient.walk( SnmpClient.oidFromString( "1.3.6.1.4.1.89.112.1.11.1.3" ), String.class, ( oid, value ) -> {

			byte[] macAddress = extractMacAddress( oid );
			IpAddress macAddressObj = new IpAddress( macAddress );

			String[] data = result.computeIfAbsent( macAddressObj, ( k ) -> new String[5] );

			data[2] = value;
		} );

		snmpClient.walk( SnmpClient.oidFromString( "1.3.6.1.4.1.89.112.1.11.1.4" ), String.class, ( oid, value ) -> {

			byte[] macAddress = extractMacAddress( oid );
			IpAddress macAddressObj = new IpAddress( macAddress );

			String[] data = result.computeIfAbsent( macAddressObj, ( k ) -> new String[5] );

			data[1] = value;
		} );

		StringBuilder sb = new StringBuilder();

		sb.append( "MAC Address\tIP Address\tLease (sec)\tType\tVLAN\tInterface" );

		result.forEach( ( k, v ) -> {
			sb.append( MACParser.macAddressToString( k.address ) ).append( '\t' )
			  .append( v[0] ).append( '\t' )
			  .append( v[1] ).append( '\t' )
			  .append( v[2] ).append( '\t' )
			  .append( v[3] ).append( '\t' )
			  .append( v[4] ).append( '\n' );
		} );

		result.clear();

		return sb.toString();
	}
}
