contract RigCraftPresalePackageManager
{
    address owner;
    
    bool public isActive;
    
    uint16[]    public presalePackSold;
    uint16[]    public presalePackLimit;
    uint256[]   public presalePackagePrice;
    
    mapping(address=>uint256) addressRefferedCount;
    mapping(address=>uint256) addressRefferredSpending;
    address[] referralAddressIndex;
    
    uint256 public totalFundsSoFar;
    
    RigCraftPresalePackageToken private presaleTokenContract;
    
    function RigCraftPresalePackageManager() public
    {
        owner = msg.sender;
        isActive = false;
        presaleTokenContract = RigCraftPresalePackageToken(address(0));
        
        presalePackSold.length     = 5;
        presalePackLimit.length    = 5;
        presalePackagePrice.length = 5;
       
        // starter pack 
        presalePackLimit[0]    = 65000;
        presalePackagePrice[0] = 0.1 ether;
        
        // snow white
        presalePackLimit[1]    = 50;
        presalePackagePrice[1] = 0.33 ether;
        
        // 6x66 black
        presalePackLimit[2]    = 66;
        presalePackagePrice[2] = 0.66 ether;
        
        // blue legandary
        presalePackLimit[3]    = 50;
        presalePackagePrice[3] = 0.99 ether;
        
        // lifetime share
        presalePackLimit[4]    = 100;
        presalePackagePrice[4] = 1 ether;
    }
    
    function SetActive(bool _active) external
    {
        require(msg.sender == owner);
        isActive = _active;
    } 
    
    function SetPresaleHandler(address addr) external
    {
        require(msg.sender == owner);
        presaleTokenContract = RigCraftPresalePackageToken(addr);
    }
    
    function AddNewPresalePackage(uint16 limit, uint256 price) external 
    {
        require(msg.sender == owner);
        require(limit > 0);
        require(isActive);
        
        presalePackLimit.length += 1;
        presalePackLimit[presalePackLimit.length-1] = limit;
        
        presalePackagePrice.length += 1;
        presalePackagePrice[presalePackagePrice.length-1] = price;
        
        presalePackSold.length += 1;
    }
    
    // ETH handler
    function BuyPresalePackage(uint8 packageId, address referral) external payable
    {
        require(isActive);
        require(packageId < presalePackLimit.length);
        require(msg.sender != referral);
        require(presalePackLimit[packageId] > presalePackSold[packageId]);

        require(presaleTokenContract != RigCraftPresalePackageToken(address(0)));

        // check money
        require(msg.value >= presalePackagePrice[packageId]);
        
        presalePackSold[packageId]++;
        
        totalFundsSoFar += msg.value;
        
        presaleTokenContract.CreateToken(msg.sender, packageId, presalePackSold[packageId]);
        
        if(referral != address(0))
        {
            if(addressRefferedCount[referral] == 0)
            {
                referralAddressIndex.length += 1;
                referralAddressIndex[referralAddressIndex.length-1] = referral;
            }
            addressRefferedCount[referral] += 1;
            addressRefferredSpending[referral] += msg.value;
        }
    }

    // referral system 
    function GetAllReferralAddresses() external view returns (address[] referred)
    {
        referred = referralAddressIndex;
    }
    
    function GetReferredCount() external view returns (uint256)
    {
        return referralAddressIndex.length;
    }
    
    function GetReferredAt(uint256 idx) external view returns (address)
    {
        require(idx < referralAddressIndex.length);
        return referralAddressIndex[idx];
    }
    
    function GetReferralDataOfAddress(address addr) external view returns (uint256 count, uint256 spending)
    {
        count = addressRefferedCount[addr];
        spending = addressRefferredSpending[addr];
    }

    // withdraw 
    function withdraw() external
    {
        require(msg.sender == owner);
        owner.transfer(address(this).balance);
    }
}
// presale
function BuyPresalePackage(uint8 packageId, address referral) external payable
    {
        require(isActive);
        require(packageId < presalePackLimit.length);
        require(msg.sender != referral);
        require(presalePackLimit[packageId] > presalePackSold[packageId]);

        require(presaleTokenContract != RigCraftPresalePackageToken(address(0)));

        // check money
        require(msg.value >= presalePackagePrice[packageId]);
        
        presalePackSold[packageId]++;
        
        totalFundsSoFar += msg.value;
        
        presaleTokenContract.CreateToken(msg.sender, packageId, presalePackSold[packageId]);
        
        if(referral != address(0))
        {
            if(addressRefferedCount[referral] == 0)
            {
                referralAddressIndex.length += 1;
                referralAddressIndex[referralAddressIndex.length-1] = referral;
            }
            addressRefferedCount[referral] += 1;
            addressRefferredSpending[referral] += msg.value;
        }
    }
// ETH handler