contract Broker is Administration {
    // ----------------------------------------------------------------------------
    // Events
    // ----------------------------------------------------------------------------
    event BrokerRegistered(uint indexed brokerId, address indexed broker);
    event AppendSubBroker(uint indexed brokerId, uint indexed subBrokerId, address indexed subBroker);
    event BrokerTransfer(address indexed newBroker, uint indexed brokerId, uint indexed subBrokerId);
    event BrokerFeeDistrubution(uint brokerId, address indexed vipBroker, uint indexed vipShare, uint subBrokerId, address indexed broker, uint share);
    event BrokerFeeClaim(address indexed broker, uint indexed fee);
    
    // ----------------------------------------------------------------------------
    // Mappings
    // ----------------------------------------------------------------------------
    mapping (uint => address[]) BrokerIdToBrokers;
    mapping (uint => uint) BrokerIdToSpots;
    mapping (address => uint) BrokerIncoming;
    mapping (address => bool) UserToIfBroker;
    
    // ----------------------------------------------------------------------------
    // Variables
    // ----------------------------------------------------------------------------
    uint public vipBrokerFee = 5 ether;
    uint public brokerFee = 1.5 ether;
    uint public vipBrokerNum = 1000;
    uint public subBrokerNum = 5;
    
    // ----------------------------------------------------------------------------
    // Modifier
    // ----------------------------------------------------------------------------
    
    // ----------------------------------------------------------------------------
    // Internal Function
    // ----------------------------------------------------------------------------
    function _brokerFeeDistribute(uint _price, uint _type, uint _brokerId, uint _subBrokerId) internal {
        address vipBroker = getBrokerAddress(_brokerId, 0);
        address broker = getBrokerAddress(_brokerId, _subBrokerId);
        require(vipBroker != address(0) && broker != address(0));
        uint totalShare = _price*rewardPercent[_type]/100;
        BrokerIncoming[vipBroker] = BrokerIncoming[vipBroker] + totalShare*15/100;
        BrokerIncoming[broker] = BrokerIncoming[broker] + totalShare*85/100;
        
        emit BrokerFeeDistrubution(_brokerId, vipBroker, totalShare*15/100, _subBrokerId, broker, totalShare*85/100);
    }
    
    // ----------------------------------------------------------------------------
    // Public Function
    // ----------------------------------------------------------------------------
    function registerBroker() public payable returns (uint) {
        require(vipBrokerNum > 0);
        require(msg.value >= vipBrokerFee);
        require(UserToIfBroker[msg.sender] == false);
        UserToIfBroker[msg.sender] = true;
        vipBrokerNum--;
        uint brokerId = 1000 - vipBrokerNum;
        BrokerIdToBrokers[brokerId].push(msg.sender);
        BrokerIdToSpots[brokerId] = subBrokerNum;
        emit BrokerRegistered(brokerId, msg.sender);
        return brokerId;
    }
    
    function assignSubBroker(uint _brokerId, address _broker) public payable {
        require(msg.sender == BrokerIdToBrokers[_brokerId][0]);
        require(msg.value >= brokerFee);
        require(UserToIfBroker[_broker] == false);
        UserToIfBroker[_broker] = true;
        require(BrokerIdToSpots[_brokerId] > 0);
        uint newSubBrokerId = BrokerIdToBrokers[_brokerId].push(_broker) - 1;
        BrokerIdToSpots[_brokerId]--;
        
        emit AppendSubBroker(_brokerId, newSubBrokerId, _broker);
    }
    
    function transferBroker(address _newBroker, uint _brokerId, uint _subBrokerId) public whenNotPaused {
        require(_brokerId > 0 && _brokerId <= 1000);
        require(_subBrokerId >= 0 && _subBrokerId <= 5);
        require(UserToIfBroker[msg.sender] == true);
        UserToIfBroker[msg.sender] = false;
        require(BrokerIdToBrokers[_brokerId][_subBrokerId] == msg.sender);
        BrokerIdToBrokers[_brokerId][_subBrokerId] = _newBroker;
        
        emit BrokerTransfer(_newBroker, _brokerId, _subBrokerId);
    }

    function claimBrokerFee() public whenNotPaused {
        uint fee = BrokerIncoming[msg.sender];
        require(fee > 0);
        msg.sender.transfer(fee);
        BrokerIncoming[msg.sender] = 0;
        emit BrokerFeeClaim(msg.sender, fee);
    }
    
    function getBrokerIncoming(address _broker) public view returns (uint) {
        return BrokerIncoming[_broker];
    } 
    
    function getBrokerInfo(uint _brokerId) public view returns (
        address broker,
        uint subSpot
    ) { 
        broker = BrokerIdToBrokers[_brokerId][0];
        subSpot = BrokerIdToSpots[_brokerId];
    }
    
    function getBrokerAddress(uint _brokerId, uint _subBrokerId) public view returns (address) {
        return BrokerIdToBrokers[_brokerId][_subBrokerId];
    }
    
    function getVipBrokerNum() public view returns (uint) {
        return safeSub(1000, vipBrokerNum);
    }
}
function registerBroker() public payable returns (uint) {
    require(vipBrokerNum > 0);
    require(msg.value >= vipBrokerFee);
    require(UserToIfBroker[msg.sender] == false);
    UserToIfBroker[msg.sender] = true;
    vipBrokerNum--;
    uint brokerId = 1000 - vipBrokerNum;
    BrokerIdToBrokers[brokerId].push(msg.sender);
    BrokerIdToSpots[brokerId] = subBrokerNum;
    emit BrokerRegistered(brokerId, msg.sender);
    return brokerId;
}

// ----------------------------------------------------------------------------
// Public Function
// ----------------------------------------------------------------------------