contract SpaceportFactory is Ownable {
    using EnumerableSet for EnumerableSet.AddressSet;
    
    EnumerableSet.AddressSet private spaceports;
    EnumerableSet.AddressSet private spaceportGenerators;
    
    mapping(address => EnumerableSet.AddressSet) private spaceportOwners;
    
    event spaceportRegistered(address spaceportContract);
    
    function adminAllowSpaceportGenerator (address _address, bool _allow) public onlyOwner {
        if (_allow) {
            spaceportGenerators.add(_address);
        } else {
            spaceportGenerators.remove(_address);
        }
    }
    
    /**
     * @notice Called by a registered SpaceportGenerator upon Spaceport creation
     */
    function registerSpaceport (address _spaceportAddress) public {
        require(spaceportGenerators.contains(msg.sender), 'FORBIDDEN');
        spaceports.add(_spaceportAddress);
        emit spaceportRegistered(_spaceportAddress);
    }
    
    /**
     * @notice Number of allowed SpaceportGenerators
     */
    function spaceportGeneratorsLength() external view returns (uint256) {
        return spaceportGenerators.length();
    }
    
    /**
     * @notice Gets the address of a registered SpaceportGenerator at specified index
     */
    function spaceportGeneratorAtIndex(uint256 _index) external view returns (address) {
        return spaceportGenerators.at(_index);
    }
    
    /**
     * @notice Returns true if the spaceport address was generated by the Plfi spaceport platform
     */
    function spaceportIsRegistered(address _spaceportAddress) external view returns (bool) {
        return spaceports.contains(_spaceportAddress);
    }
    
    /**
     * @notice The length of all spaceports on the platform
     */
    function spaceportsLength() external view returns (uint256) {
        return spaceports.length();
    }
    
    /**
     * @notice Gets a spaceport at a specific index. Although using Enumerable Set, since spaceports are only added and not removed, indexes will never change
     * @return The address of the Spaceport contract at index
     */
    function spaceportAtIndex(uint256 _index) external view returns (address) {
        return spaceports.at(_index);
    }
    
}
function spaceportGeneratorAtIndex(uint256 _index) external view returns (address) {
    return spaceportGenerators.at(_index);
}

/**
 * @notice Gets the address of a registered SpaceportGenerator at specified index
 */