// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {ERC20} from "@openzeppelin-contracts/token/ERC20/ERC20.sol";
import {ERC20Permit} from "@openzeppelin-contracts/token/ERC20/extensions/ERC20Permit.sol";
import {ERC20Votes} from "@openzeppelin-contracts/token/ERC20/extensions/ERC20Votes.sol";
import {Nonces} from "@openzeppelin-contracts/utils/Nonces.sol";

import {ISTNK} from "./interfaces/ISTNK.sol";
import {IGHST} from "./interfaces/IGHST.sol";
import {FullMath} from "./libraries/FullMath.sol";

contract Ghost is IGHST, ERC20, ERC20Permit, ERC20Votes {
    address public override staking;
    address public override stnk;
    address private _initializer;

    error GhostDelegationIsBuiltIn();

    constructor(address _stnk, string memory name, string memory symbol)
        ERC20(name, symbol)
        ERC20Permit(name)
    {
        stnk = _stnk;
        _initializer = msg.sender;
    }

    function initialize(address _staking) external {
        if (msg.sender != _initializer) revert NotStakingContract();
        staking = _staking;
        _initializer = address(0);
    }

    function mint(address _to, uint256 _amount) external override {
        if (msg.sender != staking) revert NotStakingContract();
        _mint(_to, _amount);
    }

    function burn(address _from, uint256 _amount) external override {
        if (msg.sender != staking) revert NotStakingContract();
        _burn(_from, _amount);
    }

    function delegate(address) public override pure {
        revert GhostDelegationIsBuiltIn();
    }

    function delegateBySig(
        address,
        uint256,
        uint256,
        uint8,
        bytes32,
        bytes32
    ) public override pure {
        revert GhostDelegationIsBuiltIn();
    }

    function index() public view override returns (uint256) {
        return ISTNK(stnk).index();
    }

    function balanceFrom(uint256 _amount) public view override returns (uint256) {
        return FullMath.mulDiv(_amount, index(), 1e18);
    }

    function balanceTo(uint256 _amount) public view override returns (uint256) {
        return FullMath.mulDiv(_amount, 1e18, index());
    }

    function nonces(address owner) public view override(ERC20Permit, Nonces) returns (uint256) {
        return super.nonces(owner);
    }

    function delegates(address account) public pure override returns (address) {
        return account;
    }

    function _update(address from, address to, uint256 amount) internal override(ERC20, ERC20Votes) {
        super._update(from, to, amount);
    }
}
