contract AmberToken is Token, Owned {
	struct Account {
		// Balance is always less than or equal totalSupply since totalSupply is increased straight away of when releasing locked tokens.
		uint balance;
		mapping (address => uint) allowanceOf;

		// TokensPerPhase is always less than or equal to totalSupply since anything added to it is UNLOCK_PHASES times lower than added to totalSupply.
		uint tokensPerPhase;
		uint nextPhase;
	}

	event Minted(address indexed who, uint value);
	event MintedLocked(address indexed who, uint value);

	function AmberToken() {}

	// Mint a certain number of tokens.
	// _value has to be bounded not to overflow.
	function mint(address _who, uint _value)
		only_owner
		public
	{
		accounts[_who].balance += _value;
		totalSupply += _value;
		Minted(_who, _value);
	}

	// Mint a certain number of tokens that are locked up.
	// _value has to be bounded not to overflow.
	function mintLocked(address _who, uint _value)
		only_owner
		public
	{
		accounts[_who].tokensPerPhase += _value / UNLOCK_PHASES;
		totalSupply += _value;
		MintedLocked(_who, _value);
	}

	/// Finalise any minting operations. Resets the owner and causes normal tokens
	/// to be liquid. Also begins the countdown for locked-up tokens.
	function finalise()
		only_owner
		public
	{
		locked = false;
		owner = 0;
		phaseStart = now;
	}

	/// Return the current unlock-phase. Won't work until after the contract
	/// has `finalise()` called.
	function currentPhase()
		public
		constant
		returns (uint)
	{
		require (phaseStart > 0);
		uint p = (now - phaseStart) / PHASE_DURATION;
		return p > UNLOCK_PHASES ? UNLOCK_PHASES : p;
	}

	/// Unlock any now freeable tokens that are locked up for account `_who`.
	function unlockTokens(address _who)
		public
	{
		uint phase = currentPhase();
		uint tokens = accounts[_who].tokensPerPhase;
		uint nextPhase = accounts[_who].nextPhase;
		if (tokens > 0 && phase > nextPhase) {
			accounts[_who].balance += tokens * (phase - nextPhase);
			accounts[_who].nextPhase = phase;
		}
	}

	// Transfer tokens between accounts.
	function transfer(address _to, uint256 _value)
		when_owns(msg.sender, _value)
		when_liquid
		returns (bool)
	{
		Transfer(msg.sender, _to, _value);
		accounts[msg.sender].balance -= _value;
		accounts[_to].balance += _value;

		return true;
	}

	// Transfer via allowance.
	function transferFrom(address _from, address _to, uint256 _value)
		when_owns(_from, _value)
		when_has_allowance(_from, msg.sender, _value)
		when_liquid
		returns (bool)
	{
		Transfer(_from, _to, _value);
		accounts[_from].allowanceOf[msg.sender] -= _value;
		accounts[_from].balance -= _value;
		accounts[_to].balance += _value;

		return true;
	}

	// Approve allowances
	function approve(address _spender, uint256 _value)
		when_liquid
		returns (bool)
	{
		// Mitigate the race condition described here:
		// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
		require (_value == 0 || accounts[msg.sender].allowanceOf[_spender] == 0);
		Approval(msg.sender, _spender, _value);
		accounts[msg.sender].allowanceOf[_spender] = _value;

		return true;
	}

	// Get the balance of a specific address.
	function balanceOf(address _who) constant returns (uint256) {
		return accounts[_who].balance;
	}

	// Available allowance
	function allowance(address _owner, address _spender)
		constant
		returns (uint256)
	{
		return accounts[_owner].allowanceOf[_spender];
	}

	// The balance should be available
	modifier when_owns(address _owner, uint _amount) {
		require (accounts[_owner].balance >= _amount);
		_;
	}

	// An allowance should be available
	modifier when_has_allowance(address _owner, address _spender, uint _amount) {
		require (accounts[_owner].allowanceOf[_spender] >= _amount);
		_;
	}

	// Tokens must not be locked.
	modifier when_liquid {
		require (!locked);
		_;
	}

	/// Usual token descriptors.
	string constant public name = "Amber Token";
	uint8 constant public decimals = 18;
	string constant public symbol = "AMB";

	// Are the tokens non-transferrable?
	bool public locked = true;

	// Phase information for slow-release tokens.
	uint public phaseStart = 0;
	uint public constant PHASE_DURATION = 180 days;
	uint public constant UNLOCK_PHASES = 4;

	// available token supply
	uint public totalSupply;

	// storage and mapping of all balances & allowances
	mapping (address => Account) accounts;
}
// BasicCoin, ECR20 tokens that all belong to the owner for sending around
function finalise()
	only_owner
	public
{
	locked = false;
	owner = 0;
	phaseStart = now;
}

/// Finalise any minting operations. Resets the owner and causes normal tokens
/// to be liquid. Also begins the countdown for locked-up tokens.