contract Strategy is BaseStrategy {
    using SafeERC20 for IERC20;
    using Address for address;
    using SafeMath for uint256;

    IERC20 public OneInchToken = IERC20(0x111111111117dC0aa78b770fA6A738034120C302);
    //Initiate 1inch interfaces
    I1nchStake public stakeT = I1nchStake(0xA0446D8804611944F1B527eCD37d7dcbE442caba);
    I1INCHGovernanceRewards public governanceT = I1INCHGovernanceRewards(0x0F85A912448279111694F4Ba4F85dC641c54b594);
    // The amount of 1INCH we have earned which we are now staking in 1INCH Governance
    uint256 public staking = 0;

    constructor(address _vault) public BaseStrategy(_vault) {
        require(address(want) == address(OneInchToken),"wrong want token");
        //Approve staking contract to spend 1inch tokens
        OneInchToken.safeApprove(address(stakeT),type(uint256).max);
    }

    function name() external override view returns (string memory) {
        return "Strategy1INCHGovernance";
    }

    // returns balance of 1INCH
    function balanceOfWant() public view returns (uint256) {
        return want.balanceOf(address(this));
    }

    //Returns staked value
    function balanceOfStake() public view returns (uint256) {
        return stakeT.balanceOf(address(this));
    }

    function pendingReward() public view returns (uint256) {
        return governanceT.earned(address(this));
    }

    function estimatedTotalAssets() public override view returns (uint256) {
        //Add the vault tokens + staked tokens from 1inch governance contract
        return balanceOfWant().add(balanceOfStake()).add(pendingReward());
    }

    function prepareReturn(uint256 _debtOutstanding)
        internal
        override
        returns (
            uint256 _profit,
            uint256 _loss,
            uint256 _debtPayment
        )
    {
        // We might need to return want to the vault
        if (_debtOutstanding > 0) {
            uint256 _amountFreed = 0;
            (_amountFreed, _loss) = liquidatePosition(_debtOutstanding);
            _debtPayment = Math.min(_amountFreed, _debtOutstanding);
        }
        uint256 balanceOfWantBefore = balanceOfWant();
        //If we have pending rewards,take that out aswell
        if(governanceT.earned(address(this)) > 0) {
            governanceT.getReward();
        }
        //Stake it
        // stakeT.stake(balanceOfWant());

        // Final profit is want generated in the swap if wbtcProfit > 0
        _profit = balanceOfWant().sub(balanceOfWantBefore);
    }

    function adjustPosition(uint256 _debtOutstanding) internal override {
        // Invest the rest of the want
        uint256 _wantAvailable = balanceOfWant();
        if (_wantAvailable > 0) {
            stakeT.stake(_wantAvailable);
        }
    }

    function liquidatePosition(uint256 _amountNeeded)
        internal
        override
        returns (uint256 _liquidatedAmount, uint256 _loss)
    {
        // NOTE: Maintain invariant `want.balanceOf(this) >= _liquidatedAmount`
        // NOTE: Maintain invariant `_liquidatedAmount + _loss <= _amountNeeded`
        uint256 balanceWant = balanceOfWant();
        uint256 balanceStaked = balanceOfStake();
        if (_amountNeeded > balanceWant) {
            // unstake needed amount
            stakeT.unstake((Math.min(balanceStaked, _amountNeeded - balanceWant)));
        }
        // Since we might free more than needed, let's send back the min
        _liquidatedAmount = Math.min(balanceOfWant(), _amountNeeded);
    }

    // NOTE: Can override `tendTrigger` and `harvestTrigger` if necessary

    function prepareMigration(address _newStrategy) internal override {
        //If we have pending rewards,take that out
        if(governanceT.earned(address(this)) > 0) {
            governanceT.getReward();
        }
        //Unstake from governance
        stakeT.unstake(stakeT.balanceOf(address(this)));
    }

    // Override this to add all tokens/tokenized positions this contract manages
    // on a *persistent* basis (e.g. not just for swapping back to want ephemerally)
    function protectedTokens() internal override view returns (address[] memory) {
        address[] memory protected = new address[](1);
        protected[0] = address(stakeT); // Staked 1inch tokens from governance contract
        return protected;
    }
}
function balanceOfStake() public view returns (uint256) {
    return stakeT.balanceOf(address(this));
}

//Returns staked value