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

import {ERC721MetadataStorage} from "@solidstate/contracts/token/ERC721/metadata/ERC721MetadataStorage.sol";
import {IERC721} from "@solidstate/contracts/token/ERC721/IERC721.sol";
import {Proxy} from "@solidstate/contracts/proxy/Proxy.sol";
import {SafeOwnable, OwnableStorage} from "@solidstate/contracts/access/SafeOwnable.sol";
import {IERC165} from "@solidstate/contracts/introspection/IERC165.sol";

import {ERC165Storage} from "@solidstate/contracts/introspection/ERC165Storage.sol";
import {ChonkySpecialStorage} from "./ChonkySpecialStorage.sol";

contract ChonkySpecialProxy is Proxy, SafeOwnable {
    using ChonkySpecialStorage for OwnableStorage.Layout;
    using OwnableStorage for OwnableStorage.Layout;
    using ERC165Storage for ERC165Storage.Layout;

    event Upgraded(
        address indexed oldImplementation,
        address indexed newImplementation
    );

    constructor(address implementation) {
        OwnableStorage.layout().setOwner(msg.sender);
        ChonkySpecialStorage.layout().implementation = implementation;

        {
            ERC721MetadataStorage.Layout storage l = ERC721MetadataStorage
                .layout();
            l.name = "Chonkys Special";
            l.symbol = "CKSP";
        }

        {
            ERC165Storage.Layout storage l = ERC165Storage.layout();
            l.setSupportedInterface(type(IERC165).interfaceId, true);
            l.setSupportedInterface(type(IERC721).interfaceId, true);
        }
    }

    function _getImplementation() internal view override returns (address) {
        return ChonkySpecialStorage.layout().implementation;
    }

    function getImplementation() external view returns (address) {
        return _getImplementation();
    }

    function setImplementation(address implementation) external onlyOwner {
        address oldImplementation = ChonkySpecialStorage
            .layout()
            .implementation;
        ChonkySpecialStorage.layout().implementation = implementation;
        emit Upgraded(oldImplementation, implementation);
    }
}
[{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldImplementation","type":"address"},{"indexed":true,"internalType":"address","name":"newImplementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nomineeOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"setImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]