contract Strategy is CurveVoterProxy {
    address[] public pathTarget;
    // address public constant reward = address('[reward token address]');

    constructor(address _vault) public CurveVoterProxy(_vault) {
        curve = address(0xac795D2c97e60DF6a99ff1c814727302fD747a80);
        gauge = address(0xBC89cd85491d81C6AD2954E6d0362Ee29fCa8F53);
        keepCRV = 1000;

        _approveBasic();
        pathTarget = new address[](1);
        _setPathTarget(0, 0); // crv path target
        // _setPathTarget(1, 0); // reward path target

        dex = new address[](1);
        dex[0] = sushiswap; // crv
        // dex[1] = sushiswap; // reward
        _approveDex();
    }

    // >>> approve other rewards on dex
    // function _approveDex() internal override { super._approveDex(); }

    function _setPathTarget(uint _tokenId, uint _id) internal {
        if (_id == 0) {
            pathTarget[_tokenId] = dai;
        }
        else if (_id == 1) {
            pathTarget[_tokenId] = usdc;
        }
        else {
            pathTarget[_tokenId] = usdt;
        }
    }

    function setPathTarget(uint _tokenId, uint _id) external onlyAuthorized {
        _setPathTarget(_tokenId, _id);
    }

    function prepareReturn(uint256 _debtOutstanding)
        internal
        override
        returns (
            uint256 _profit,
            uint256 _loss,
            uint256 _debtPayment
        )
    {
        uint before = balanceOfWant();
        IVoterProxy(proxy).harvest(gauge);
        uint256 _crv = IERC20(crv).balanceOf(address(this));
        if (_crv > 0) {
            _crv = _adjustCRV(_crv);

            address[] memory path = new address[](3);
            path[0] = crv;
            path[1] = weth;
            path[2] = pathTarget[0];

            Uni(dex[0]).swapExactTokensForTokens(_crv, uint256(0), path, address(this), now);
        }
        // >>> claim reward tokens
        // >>> if more than one reward tokens, adding them all here
        // IVoterProxy(proxy).claimRewards(gauge, reward);
        // >>> sell all rewards to pathTarget[1]
        uint256 _dai = IERC20(dai).balanceOf(address(this));
        uint256 _usdc = IERC20(usdc).balanceOf(address(this));
        uint256 _usdt = IERC20(usdt).balanceOf(address(this));
        if (_dai > 0 || _usdc > 0 || _usdt > 0) {
            ICurveFi(curve).add_liquidity([_dai, _usdc, _usdt], 0);
        }
        _profit = balanceOfWant().sub(before);

        uint _total = estimatedTotalAssets();
        uint _debt = vault.strategies(address(this)).totalDebt;
        if(_total < _debt) {
            _loss = _debt - _total;
            _profit = 0;
        }

        if (_debtOutstanding > 0) {
            _withdrawSome(_debtOutstanding);
            _debtPayment = Math.min(_debtOutstanding, balanceOfWant().sub(_profit));
        }
    }

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

    function protectedTokens()
        internal
        view
        override
        returns (address[] memory)
    {
        address[] memory protected = new address[](1);
        protected[0] = crv;
        // protected[1] = reward;
        return protected;
    }
}
function protectedTokens()
    internal
    view
    override
    returns (address[] memory)
{
    address[] memory protected = new address[](1);
    protected[0] = crv;
    // protected[1] = reward;
    return protected;
}

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