abstract
contract Market is
 ERC721Burnable
{
    address payable public _contractOwner;

    mapping (uint => uint) public price;
    mapping (uint => bool) public listedMap;

    event Purchase(address indexed previousOwner, address indexed newOwner, uint price, uint nftID, string uri);

    event Minted(address indexed minter, uint256 price, uint nftID, string uri);

    event PriceUpdate(address indexed owner, uint oldPrice, uint newPrice, uint nftID);

    event NftListStatus(address indexed owner, uint nftID, bool isListed);
	
		
	//즉시 판매 생성
    function mint(string memory _tokenURI, address _toAddress, uint256 _price) public returns (uint) {
        uint _tokenId = totalSupply() + 1;
        price[_tokenId] = _price;
        listedMap[_tokenId] = true;

        _safeMint(_toAddress, _tokenId);
        _setTokenURI(_tokenId, _tokenURI);

        emit Minted(_toAddress, _price, _tokenId, _tokenURI);

        return _tokenId;
    }
	
    function buy(uint _id) external payable {
        _validate(_id);

        address _previousOwner = ownerOf(_id);
        address _newOwner = msg.sender;

        _trade(_id);

        emit Purchase(_previousOwner, _newOwner, price[_id], _id, tokenURI(_id));
    }

    function _validate(uint _id) internal {
        bool isItemListed = listedMap[_id];
        require(_exists(_id));
        require(isItemListed);
        require(msg.value >= price[_id]);
        require(msg.sender != ownerOf(_id));
    }

    function _trade(uint _id) internal {
        address payable contractOwner = payable(_owner);
        address payable _buyer = payable(msg.sender);
        address payable _owner = payable(ownerOf(_id));

        _transfer(_owner, _buyer, _id);
		

					uint _commissionValue = price[_id] * feeRate() / 1000;
			uint _sellerValue = price[_id] - _commissionValue;

			_owner.transfer(_sellerValue);
			contractOwner.transfer(_commissionValue);
		
        // If buyer sent more than price, we send them back their rest of funds
        if (msg.value > price[_id]) {
            _buyer.transfer(msg.value - price[_id]);
        }

        listedMap[_id] = false;
    }
	
    function updatePrice(uint _tokenId, uint _price) public returns (bool) {
				require(hasAuction(_tokenId) == false);
		        uint oldPrice = price[_tokenId];
        require(msg.sender == ownerOf(_tokenId));
        price[_tokenId] = _price;

        emit PriceUpdate(msg.sender, oldPrice, _price, _tokenId);
        return true;
    }
	
    function updateListingStatus(uint _tokenId, bool shouldBeListed) public returns (bool) {
        require(msg.sender == ownerOf(_tokenId));
		        require(hasAuction(_tokenId) == false);
		
        listedMap[_tokenId] = shouldBeListed;

        emit NftListStatus(msg.sender, _tokenId, shouldBeListed);

        return true;
    }	
	
    function updateSale(uint256 _tokenId, uint256 _price) public returns (bool) {
				require(hasAuction(_tokenId) == false);
		        uint oldPrice = price[_tokenId];
        require(msg.sender == ownerOf(_tokenId));
		
        price[_tokenId] = _price;
		emit NftListStatus(msg.sender, _tokenId, true);
		
		if (listedMap[_tokenId] != true) {
			listedMap[_tokenId] = true;
			emit PriceUpdate(msg.sender, oldPrice, _price, _tokenId);
		}
        return true;
    }
	
}
function mint(string memory _tokenURI, address _toAddress, uint256 _price) public returns (uint) {
    uint _tokenId = totalSupply() + 1;
    price[_tokenId] = _price;
    listedMap[_tokenId] = true;

    _safeMint(_toAddress, _tokenId);
    _setTokenURI(_tokenId, _tokenURI);

    emit Minted(_toAddress, _price, _tokenId, _tokenURI);

    return _tokenId;
}

//즉시 판매 생성