contract Releasable is Ownable {

  address public releaseAgent;
  bool public released = false;
  mapping (address => bool) public Agents;

  event ReleaseAgent(address previous, address newAgent);

  //Set the contract that can call release and make the resource operative
  function setReleaseAgent(address addr) onlyOwner inReleaseState(false) public {
    releaseAgent = addr;
    emit ReleaseAgent(releaseAgent, addr);
  }

  // Owner can allow a particular address (e.g. a crowdsale contract) to be Agent to manage the resource
  function setAgent(address addr) onlyOwner inReleaseState(false) public returns(bool){
    Agents[addr] = true;
    emit Agent(addr,true);
    return true;
  }

  // Owner forbids a particular address (e.g. a crowdsale contract) to be Agent to manage the resource
  function resetAgent(address addr) onlyOwner inReleaseState(false) public returns(bool){
    Agents[addr] = false;
    emit Agent(addr,false);
    return true;
  }
    event Agent(address addr, bool status);

  function amIAgent() public view returns (bool) {
    return Agents[msg.sender];
  }

  function isAgent(address addr) public view /*onlyOwner */ returns(bool) {
    return Agents[addr];
  }

  //From now the resource is free
  function releaseOperation() public onlyReleaseAgent {
        released = true;
		emit Released();
  }
  event Released();

  // Limit resource operative until the release
  modifier canOperate(address sender) {
    require(released || Agents[sender]);
    _;
  }

  //The function can be called only before or after the tokens have been released
  modifier inReleaseState(bool releaseState) {
    require(releaseState == released);
    _;
  }

  //The function can be called only by a whitelisted release agent.
  modifier onlyReleaseAgent() {
    require(msg.sender == releaseAgent);
    _;
  }
}
//Define interface for Manage + release a resource normal operation after an external trigger
function setAgent(address addr) onlyOwner inReleaseState(false) public returns(bool){
    Agents[addr] = true;
    emit Agent(addr,true);
    return true;
  }
// Owner can allow a particular address (e.g. a crowdsale contract) to be Agent to manage the resource