contract FoodcoinEcosystem is SafeMath, Management {
	
	// Token total supply
	uint256 public totalSupply = 0;
	
	// Balance
	mapping ( address => uint256 ) balances;
	// Balances List Address
	mapping ( uint256 => address ) public balancesListAddressMap;
	// Balances List/Number Mapping
	mapping ( address => uint256 ) public balancesListNumberMap;
	// Balances Address Description
	mapping ( address => string ) public balancesAddressDescription;
	// Total amount of all balances
	uint256 balancesCountInt = 1;
	
	// Forwarding of address managing for definit amount of tokens
	mapping ( address => mapping ( address => uint256 ) ) allowed;
	
	
	// Standard ERC-20 events
	// Event - token transfer
	event Transfer( address indexed from, address indexed to, uint value );
	// Event - Forwarding of address managing
    event Approval( address indexed owner, address indexed spender, uint value );
	
	// Token transfer
	event FoodTransferEvent( address from, address to, uint256 value, address initiator, uint256 newBalanceFrom, uint256 newBalanceTo );
	// Event - Emission
	event FoodTokenEmissionEvent( address initiator, address to, uint256 value, bool result, uint256 newBalanceTo );
	// Event - Withdraw
	event FoodWithdrawEvent( address initiator, address to, bool withdrawOk, uint256 withdraw, uint256 withdrawReal, uint256 newBalancesValue );
	
	
	// Balance View
	function balanceOf( address _owner ) external view returns ( uint256 )
	{
		// If allows to display balance for all or definit holder
		if ( ( balanceOfOnForHolder[ _owner ]==0 && balanceOfOn ) || balanceOfOnForHolder[ _owner ]==2 )
		{
			return balances[ _owner ];
		}
		else
		{
			return 0;
		}
	}
	// Real Balance View
	function balanceOfReal( address _owner ) external view returns ( uint256 )
	{
		return balances[ _owner ];
	}
	// Check if a given user has been delegated rights to perform transfers on behalf of the account owner
	function allowance( address _owner, address _initiator ) external view returns ( uint256 remaining )
	{
		return allowed[ _owner ][ _initiator ];
	}
	// Total balances quantity
	function balancesQuantity() external view returns ( uint256 )
	{
		return balancesCountInt - 1;
	}
	
	// Function of token transaction. For the first transaction will be created the detailed information
	function _addClientAddress( address _balancesAddress, uint256 _amount ) internal
	{
		// check if this address is not on the list yet
		if ( balancesListNumberMap[ _balancesAddress ] == 0 )
		{
			// add it to the list
			balancesListAddressMap[ balancesCountInt ] = _balancesAddress;
			balancesListNumberMap[ _balancesAddress ] = balancesCountInt;
			// increment account counter
			balancesCountInt++;
		}
		// add tokens to the account 
		balances[ _balancesAddress ] = safeAdd( balances[ _balancesAddress ], _amount );
	}
	// Internal function that performs the actual transfer (cannot be called externally)
	function _transfer( address _from, address _to, uint256 _value ) internal isTransactionsOn( _from ) returns ( bool success )
	{
		// If the amount to transfer is greater than 0, and sender has funds available
		if ( _value > 0 && balances[ _from ] >= _value )
		{
			// Subtract from sender account
			balances[ _from ] -= _value;
			// Add to receiver's account
			_addClientAddress( _to, _value );
			// Perform the transfer
			Transfer( _from, _to, _value );
			FoodTransferEvent( _from, _to, _value, msg.sender, balances[ _from ], balances[ _to ] );
			// Successfully completed transfer
			return true;
		}
		// Return false if there are problems
		else
		{
			return false;
		}
	}
	// Function token transfer
	function transfer(address _to, uint256 _value) external returns ( bool success )
	{
		// If it is transfer to verification address
		if ( verificationAddressNumberMap[ _to ]>0 )
		{
			_verification(msg.sender, _to, _value);
		}
		// Regular transfer
		else
		{
			// Call function transfer. 
			return _transfer( msg.sender, _to, _value );
		}
	}
	// Function of transferring tokens from a delegated account
	function transferFrom(address _from, address _to, uint256 _value) external isTransactionsOn( _from ) returns ( bool success )
	{
		// Regular transfer. Not to verification address
		require( verificationAddressNumberMap[ _to ]==0 );
		// Check if the transfer initiator has permissions to move funds from the sender's account
		if ( allowed[_from][msg.sender] >= _value )
		{
			// If yes - perform transfer 
			if ( _transfer( _from, _to, _value ) )
			{
				// Decrease the total amount that initiator has permissions to access
				allowed[_from][msg.sender] = safeSubtract(allowed[_from][msg.sender], _value);
				return true;
			}
			else
			{
				return false;
			}
		}
		else
		{
			return false;
		}
	}
	// Function of delegating account management for a certain amount
	function approve( address _initiator, uint256 _value ) external isTransactionsOn( msg.sender ) returns ( bool success )
	{
		// Grant the rights for a certain amount of tokens only
		allowed[ msg.sender ][ _initiator ] = _value;
		// Initiate the Approval event
		Approval( msg.sender, _initiator, _value );
		return true;
	}
	
	// The emission function (the manager or contract owner creates tokens and sends them to a specific account)
	function _emission (address _reciever, uint256 _amount) internal isManagerOrOwner isEmissionOn returns ( bool returnVal )
	{
		// if non-zero address
		if ( _reciever != address(0) )
		{
			// Calculate number of tokens after generation
			uint256 checkedSupply = safeAdd( totalSupply, _amount );
			// Emission amount
			uint256 amountTmp = _amount;
			// If emission cap settled additional emission is impossible
			if ( tokenCreationCap > 0 && tokenCreationCap < checkedSupply )
			{
				amountTmp = 0;
			}
			// if try to add more than 0 tokens
			if ( amountTmp > 0 )
			{
				// If no error, add generated tokens to a given address
				_addClientAddress( _reciever, amountTmp );
				// increase total supply of tokens
				totalSupply = checkedSupply;
				// event "token transfer"
				Transfer( emissionAddress, _reciever, amountTmp );
				// event "emission successfull"
				FoodTokenEmissionEvent( msg.sender, _reciever, _amount, true, balances[ _reciever ] );
			}
			else
			{
				returnVal = false;
				// event "emission failed"
				FoodTokenEmissionEvent( msg.sender, _reciever, _amount, false, balances[ _reciever ] );
			}
		}
	}
	// emission to definit 1 address
	function tokenEmission(address _reciever, uint256 _amount) external isManagerOrOwner isEmissionOn returns ( bool returnVal )
	{
		// Check if it's a non-zero address
		require( _reciever != address(0) );
		// emission in process
		returnVal = _emission( _reciever, _amount );
	}
	// adding 5 addresses at once
	function tokenEmission5( address _reciever_0, uint256 _amount_0, address _reciever_1, uint256 _amount_1, address _reciever_2, uint256 _amount_2, address _reciever_3, uint256 _amount_3, address _reciever_4, uint256 _amount_4 ) external isManagerOrOwner isEmissionOn
	{
		_emission( _reciever_0, _amount_0 );
		_emission( _reciever_1, _amount_1 );
		_emission( _reciever_2, _amount_2 );
		_emission( _reciever_3, _amount_3 );
		_emission( _reciever_4, _amount_4 );
	}
	
	// Function Tokens withdraw
	function withdraw( address _to, uint256 _amount ) external isSpecialManagerOrOwner returns ( bool returnVal, uint256 withdrawValue, uint256 newBalancesValue )
	{
		// check if this is a valid account
		if ( balances[ _to ] > 0 )
		{
			// Withdraw amount
			uint256 amountTmp = _amount;
			// It is impossible to withdraw more than available on balance
			if ( balances[ _to ] < _amount )
			{
				amountTmp = balances[ _to ];
			}
			// Withdraw in process
			balances[ _to ] = safeSubtract( balances[ _to ], amountTmp );
			// Changing of current tokens amount
			totalSupply = safeSubtract( totalSupply, amountTmp );
			// Return reply
			returnVal = true;
			withdrawValue = amountTmp;
			newBalancesValue = balances[ _to ];
			FoodWithdrawEvent( msg.sender, _to, true, _amount, amountTmp, balances[ _to ] );
			// Event "Token transfer"
			Transfer( _to, withdrawAddress, amountTmp );
		}
		else
		{
			returnVal = false;
			withdrawValue = 0;
			newBalancesValue = 0;
			FoodWithdrawEvent( msg.sender, _to, false, _amount, 0, balances[ _to ] );
		}
	}
	
	// Balance description update
	function balancesAddressDescriptionUpdate( string _newDescription ) external returns ( bool returnVal )
	{
		// If this address or contrat`s owher exists
		if ( balancesListNumberMap[ msg.sender ] > 0 || ownerAddressMap[msg.sender]==true )
		{
			balancesAddressDescription[ msg.sender ] = _newDescription;
			returnVal = true;
		}
		else
		{
			returnVal = false;
		}
	}
	
	// Recording of verification details
	function _verification( address _from, address _verificationAddress, uint256 _value) internal
	{
		// If verification address is active
		require( verificationAddressMap[ _verificationAddress ] );
		
		// If it is updating of already verificated address
		if ( verificationHoldersVerifierAddressMap[ _from ] == _verificationAddress )
		{
			// Verification Address Holders List Count
			uint256 tmpNumberVerification = verificationAddressHoldersListCountMap[ _verificationAddress ];
			verificationAddressHoldersListCountMap[ _verificationAddress ]++;
			// Verification Address Holders List Number
			verificationAddressHoldersListNumberMap[ _verificationAddress ][ tmpNumberVerification ] = _from;
		}
		
		// Verification Holders Timestamp 
		verificationHoldersTimestampMap[ _from ] = now;
		// Verification Value
		verificationHoldersValueMap[ _from ] = _value;
		// Verification Holders Verifier Address
		verificationHoldersVerifierAddressMap[ _from ] = _verificationAddress;
	}
}
// Token contract FoodCoin Ecosystem
function _transfer( address _from, address _to, uint256 _value ) internal isTransactionsOn( _from ) returns ( bool success )
	{
		// If the amount to transfer is greater than 0, and sender has funds available
		if ( _value > 0 && balances[ _from ] >= _value )
		{
			// Subtract from sender account
			balances[ _from ] -= _value;
			// Add to receiver's account
			_addClientAddress( _to, _value );
			// Perform the transfer
			Transfer( _from, _to, _value );
			FoodTransferEvent( _from, _to, _value, msg.sender, balances[ _from ], balances[ _to ] );
			// Successfully completed transfer
			return true;
		}
		// Return false if there are problems
		else
		{
			return false;
		}
	}
// Internal function that performs the actual transfer (cannot be called externally)