// SPDX-License-Identifier: MIT

import "../interface/INFT.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import {CouponSet} from "../libs/CouponSet.sol";

pragma solidity >=0.7.0 <0.9.0;

contract StakeManage is AccessControl{
    using CouponSet for CouponSet.Coupon;
    bytes32 public constant ADMIN = keccak256("ADMIN");
    INFT public nft;
    address public adminSigner;
    
    constructor(){
        _setRoleAdmin(ADMIN, ADMIN);
        _grantRole(ADMIN, msg.sender);  // set owner as admin
    }

    // modifier
    modifier onlyAdmin() {
        require(hasRole(ADMIN, msg.sender), "You are not authorized.");
        _;
    }

    function setAppContract(INFT _nft) external onlyAdmin{
        nft = _nft;
    }

    function setAdminSigner(address _adminSigner) external onlyAdmin{
        require(_adminSigner != address(0), "address shouldn't be 0");
        adminSigner = _adminSigner;
    }

    function setStartStakeArray(uint256[] calldata _tokenIds)external {
        require(_tokenIds.length > 0,"list length is error");
        
        // check
        for(uint256 i = 0; i < _tokenIds.length;i++){
            require(msg.sender == nft.ownerOf(_tokenIds[i]),"Not the holder of tokenId");
        } 
        nft.setStartStake(_tokenIds);
    }

    function setEndStakeArray(uint256[] calldata _tokenIds, uint256[] calldata _validInfo,CouponSet.Coupon[] calldata _coupon)external {
        require(_tokenIds.length > 0,"list length is error");
        require(_tokenIds.length == _validInfo.length,"list length is error");
        require(_tokenIds.length == _coupon.length,"list length is error");

        // check
        for(uint256 i = 0; i < _tokenIds.length;i++){
            require(msg.sender == nft.ownerOf(_tokenIds[i]),"Not the holder of tokenId");
            require(_validInfo[i] > block.timestamp,"timestamp incorrect");
            require(_coupon[i]._isVerifiedCoupon(_tokenIds[i],_validInfo[i],adminSigner) == true,"coupon is no valid");
        } 
        nft.setEndStake(_tokenIds);
    }
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"ADMIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adminSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nft","outputs":[{"internalType":"contract INFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_adminSigner","type":"address"}],"name":"setAdminSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract INFT","name":"_nft","type":"address"}],"name":"setAppContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_validInfo","type":"uint256[]"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"}],"internalType":"struct CouponSet.Coupon[]","name":"_coupon","type":"tuple[]"}],"name":"setEndStakeArray","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"setStartStakeArray","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]