contract INCOOOMDistributor {

    using SafeERC20 for IERC20;

    /* ====== VARIABLES ====== */
    
    address public constant incooom = 0x906642380fD9B7AA726BCe9c6AbeE7378396061B;
    address public constant sOHM = 0x04F2694C8fcee23e8Fd0dfEA1d4f5Bb8c352111F;
    address public constant wsOHM = 0xCa76543Cf381ebBB277bE79574059e32108e3E65;

    /* ====== MAPPINGS ====== */

    mapping(uint => Tiers) public tiers;
    mapping(uint => uint) public agnositcAmountClaimed;


    /* ====== STRUCTS ====== */
    
    struct Tiers {
        string tierClass;
        uint agnosticSOHMEach;
        uint supplyOfTier;
    }
    
    /* ====== CONSTRUCTOR ====== */

    constructor() {
        tiers[0] = Tiers("Common", 0, 1944);
        tiers[1] = Tiers("Gold", 0, 648);
        tiers[2] = Tiers("Psychedelic", 0, 324);
    }
    
    /* ====== PUBLIC FUNCTIONS ====== */

    /**
    *   @notice lets anyone depoist sOHM and distributes among NFT holders
    *   @param _amountSOHM uint
    */
    function deposit(uint _amountSOHM) external {
        IERC20(sOHM).safeTransferFrom(msg.sender, address(this), _amountSOHM);
        uint _agnosticAmountTotal = IwsOHM(wsOHM).sOHMTowOHM(_amountSOHM);

        uint[3] memory _agnosticEach;

        _agnosticEach[0] = (_agnosticAmountTotal * 5813953488 / (10 ** 10));
        _agnosticEach[1] = (_agnosticAmountTotal * 2577519380 / (10 ** 10));
        _agnosticEach[2] = (_agnosticAmountTotal * 1608527132 / (10 ** 10));
        
        for(uint i = 0; i < 3; i++ ) {
            Tiers memory tier = tiers[i];
            tier.agnosticSOHMEach += _agnosticEach[i] / tier.supplyOfTier;
            tiers[i] = tier;
        }
    }

    /* ======== USER FUNCTIONS ======== */

    /**
    *   @notice allows a NFT holder to claim the underlying sOHM
    *   @param _id uint
    *   @param _recipient address
    */
    function claimUnderlying(uint[] memory _id, address _recipient) external {
        uint _amount;
        
        for(uint i; i < _id.length; i++) {
            require(IERC721(incooom).ownerOf(_id[i]) == msg.sender, "Not owner of NFT");
        
            uint underlying = getUnderlyingForNFT(_id[i], false);

            agnositcAmountClaimed[_id[i]] += getUnderlyingForNFT(_id[i], true);
            _amount += underlying;
        }
        
        IERC20(sOHM).safeTransfer(_recipient, _amount);
    }


    /* ====== VIEW FUNCTIONS ====== */

    /**
    *   @notice returns the tier of the id passed in
    *   @param _id uint
    *   @return _tier uint 
    */
    function getTier(uint _id) public view returns(uint _tier) {
        IIncooom.CardInfo memory _cardInfo = IIncooom(incooom).getCardInfo(_id);
        _tier = _cardInfo.tier;
    }

    /**
    *   @notice returns amount of sOHM (agnoatic or regular) a NFT has to claim
    *   @param _id uint
    *   @param _agnostic bool
    *   @return uint
    */
    function getUnderlyingForNFT(uint _id, bool _agnostic) public view returns (uint) {

        uint _tier = getTier(_id);

        Tiers memory tier = tiers[_tier];
        if(_agnostic){
            return tier.agnosticSOHMEach - agnositcAmountClaimed[_id];
        } else {
            return IwsOHM(wsOHM).wOHMTosOHM( tier.agnosticSOHMEach - agnositcAmountClaimed[_id]);
        }
    }   
    
}
function getUnderlyingForNFT(uint _id, bool _agnostic) public view returns (uint) {

    uint _tier = getTier(_id);

    Tiers memory tier = tiers[_tier];
    if(_agnostic){
        return tier.agnosticSOHMEach - agnositcAmountClaimed[_id];
    } else {
        return IwsOHM(wsOHM).wOHMTosOHM( tier.agnosticSOHMEach - agnositcAmountClaimed[_id]);
    }
}   

/**
 *   @notice returns amount of sOHM (agnoatic or regular) a NFT has to claim
 *   @param _id uint
 *   @param _agnostic bool
 *   @return uint
 */