contract Managed {
  event DeclareEmergency (string _reason);
  event ResolveEmergency ();

  address private addressOfOwner;
  address[] private addressesOfAdmins;
  bool private isInEmergency;

  constructor () public {
    addressOfOwner = msg.sender;
    isInEmergency = false;
  }

  /* Modifiers */
  modifier onlyOwner () {
    require(addressOfOwner == msg.sender);
    _;
  }

  modifier onlyAdmins () {
    require(isAdmin(msg.sender));
    _;
  }

  modifier notEmergency () {
    require(!isInEmergency);
    _;
  }

  /* Admin */
  function transferOwnership (address _owner) onlyOwner() public {
    clearAdmins();
    addressOfOwner = _owner;
  }

  function addAdmin (address _admin) onlyOwner() public {
    addressesOfAdmins.push(_admin);
  }

  function removeAdmin (address _admin) onlyOwner() public {
    require(isAdmin(_admin));

    uint256 length = addressesOfAdmins.length;
    address swap = addressesOfAdmins[length - 1];
    uint256 index = 0;

    for (uint256 i = 0; i < length; i++) {
      if (addressesOfAdmins[i] == _admin) {
        index = i;
      }
    }

    addressesOfAdmins[index] = swap;
    delete addressesOfAdmins[length - 1];
    addressesOfAdmins.length--;
  }

  function clearAdmins () onlyOwner() public {
    require(addressesOfAdmins.length > 0);
    addressesOfAdmins.length = 0;
  }

  /* Emergency protocol */
  function declareEmergency (string _reason) onlyOwner() public {
    require(!isInEmergency);
    isInEmergency = true;
    emit DeclareEmergency(_reason);
  }

  function resolveEmergency () onlyOwner() public {
    require(isInEmergency);
    isInEmergency = false;
    emit ResolveEmergency();
  }

  /* Read */
  function owner () public view returns (address _owner) {
    return addressOfOwner;
  }

  function admins () public view returns (address[] _admins) {
    return addressesOfAdmins;
  }

  function emergency () public view returns (bool _emergency) {
    return isInEmergency;
  }

  function isAdmin (address _admin) public view returns (bool _isAdmin) {
    if (_admin == addressOfOwner) {
      return true;
    }

    for (uint256 i = 0; i < addressesOfAdmins.length; i++) {
      if (addressesOfAdmins[i] == _admin) {
        return true;
      }
    }

    return false;
  }
}
function owner () public view returns (address _owner) {
  return addressOfOwner;
}

/* Read */