contract feesProtocolSetup is feesProtocolStorage{
    
    function changeProtocolOnDex(address _newAddress, address[] memory _tokens) public onlyOwner{
        address old = address(this); 
        require(dex != address(0), "DEX address not found!"); 
        require(old == address(this), "Old Protocol Error!"); 
        
        DEXplatform(dex).changeProtocol(_newAddress, _tokens);
        emit ChangeProtocol(old, _newAddress); 
    }
    
    function setTokenDetails(address _token, uint _amount, uint _ether) public onlyOwner{
        require(tokenIsRecieved==false, "token is already unlocked and cant changed");
        require(_amount>0, "Invalid Token Amount");
        require(_ether>0, "Invalid Ether Amount");
        projectToken = _token;
        propertyAmount = _amount;
        propertyAmountETH = _ether;
    }
    
    function setDex(address _dex) public onlyOwner{
        dex = _dex; 
    }
    
    // Deposit and Lock => Must be called receiveApproval not lockToken
    function receiveApproval(address _spender, uint _amount, address _reciver) public payable {
        require(tokenIsRecieved==false, "Token is already recieved!"); 
        require(projectToken != address(0), "Token Address hasn't set yet!");
        require(projectToken == msg.sender, "Deposting incorrect Token!");
        require(dex != address(0), "DEX is not set!"); 
        require(propertyAmount>0, "Locked amount is not set!"); 
        require(propertyAmountETH>0, "ETH amount is not set!");
        require(propertyAmount==_amount, "Recieved amount Error!");
        require(_reciver == address(this), "Approved failed!");
        require(_spender == owner, "only owner!");
        
        if (!Token(projectToken).transferFrom(_spender, address(this), _amount)) { revert("Amoount not recieved!"); }
        
        admin = _spender;
        tokenIsRecieved=true;
        
        groupsAdmin[1]=_spender;
        groupsAdmin[2]=_spender;
        groupsAdmin[3]=_spender;
        groupsAdmin[4]=_spender;
        groupsAdmin[5]=_spender;
        groupsAdmin[6]=_spender;
        
        OwnershipTotalAllocation= _amount; 
        tokenGroupsOwnershipAllocation[1]= _amount; 
        
        emit Deposit(projectToken, _spender, _amount, tokenOwnersBalance[1][_spender]);
        
    }
    
    //-----------------------------------------------------
    // Token Owndership Management 
    //-----------------------------------------------------
    
    function setGroupsAllocation(uint _amount, uint _group)public onlyOwner{
        uint freeAllocation = propertyAmount-OwnershipTotalAllocation;
        require(freeAllocation >= _amount, "Insufficient amount!"); 
        tokenGroupsOwnershipAllocation[_group]= SafeMath.safeAdd(tokenGroupsOwnershipAllocation[_group], _amount);
        OwnershipTotalAllocation = SafeMath.safeAdd(OwnershipTotalAllocation, _amount);
    }
    
    function setGroupsReAllocation(uint _amount, uint _group, uint _groupSpender)public onlyOwner{
        uint freeAllocated = tokenGroupsOwnershipAllocation[_groupSpender] - tokenGroupsOwnershipAlloced[_groupSpender]; // for re-allocating free amount not allocated
        require(groupsAdmin[_groupSpender] == msg.sender, "group admin Error!");
        require(freeAllocated >= _amount, "amount exceeding!");
        tokenGroupsOwnershipAllocation[_groupSpender]= SafeMath.safeSub(tokenGroupsOwnershipAllocation[_groupSpender], _amount);
        tokenGroupsOwnershipAllocation[_group]= SafeMath.safeAdd(tokenGroupsOwnershipAllocation[_group], _amount);
    }
    
    function allocateOwnershipToAddress(uint _amount, uint _group, address _reciver)public onlyOwner{
        // Get the amount that hasnot allocted to address [free to re-allocate]
        uint freeAllocation = tokenGroupsOwnershipAllocation[_group] - tokenGroupsOwnershipAlloced[_group];
        // Revert allocated from passing Total amount that set to be allocating
        require(SafeMath.safeAdd(OwnershipTotalAllocated, _amount) <= OwnershipTotalAllocation, "Insufficient amount!"); 
        require(groupsAdmin[_group] == msg.sender, "permission error!");
        require(freeAllocation >= _amount, "Insufficient free balance!");
        
        tokenOwnersBalance[_group][_reciver] = SafeMath.safeAdd(tokenOwnersBalance[_group][_reciver], _amount);
        tokenGroupsOwnershipAlloced[_group]= SafeMath.safeAdd(tokenGroupsOwnershipAlloced[_group], _amount);
        OwnershipTotalAllocated= SafeMath.safeAdd(OwnershipTotalAllocated, _amount);
        
        if(_group == 1){
            founders.push(_reciver);
        } else if(_group == 2){
            team.push(_reciver);
        } else if(_group == 3){
            investors.push(_reciver);
        }
    }
    
    
}
function receiveApproval(address _spender, uint _amount, address _reciver) public payable {
    require(tokenIsRecieved==false, "Token is already recieved!"); 
    require(projectToken != address(0), "Token Address hasn't set yet!");
    require(projectToken == msg.sender, "Deposting incorrect Token!");
    require(dex != address(0), "DEX is not set!"); 
    require(propertyAmount>0, "Locked amount is not set!"); 
    require(propertyAmountETH>0, "ETH amount is not set!");
    require(propertyAmount==_amount, "Recieved amount Error!");
    require(_reciver == address(this), "Approved failed!");
    require(_spender == owner, "only owner!");
        
    if (!Token(projectToken).transferFrom(_spender, address(this), _amount)) { revert("Amoount not recieved!"); }
        
    admin = _spender;
    tokenIsRecieved=true;
        
    groupsAdmin[1]=_spender;
    groupsAdmin[2]=_spender;
    groupsAdmin[3]=_spender;
    groupsAdmin[4]=_spender;
    groupsAdmin[5]=_spender;
    groupsAdmin[6]=_spender;
        
    OwnershipTotalAllocation= _amount; 
    tokenGroupsOwnershipAllocation[1]= _amount; 
        
    emit Deposit(projectToken, _spender, _amount, tokenOwnersBalance[1][_spender]);
        
}

// Deposit and Lock => Must be called receiveApproval not lockToken