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

import "erc721a/contracts/ERC721A.sol";
import "erc721a/contracts/extensions/ERC721ABurnable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

/**
 * DG Realta Parallela Collection.
 * https://drops.unxd.com/dgfamily
 */
contract DGRealtaParallela is ERC721A, ERC721ABurnable, Pausable, Ownable {

	// royalty percentage for secondary sales in UNXD marketplace.
	uint256 public royaltyPercentage = 10;

	// status flag for when minting is allowed. once the required amount of tokens are minted, this will be stopped.
	bool public mintingAllowed = true;

	// base uri for collection.
	string private baseURI = "https://nfts.unxd.com/nfts/dg-realta-parallela/";

	// royalty % change event.
	event RoyaltyPercentageChanged(uint256 indexed newPercentage);

	// minting status change event.
	event MintingStatusChanged(bool indexed status);

	// base URI updated event.
	event BaseUriUpdated(string indexed uri);

	constructor() ERC721A("DGRealtaParallela", "DGRP") {}

	/*****************************************************************************************************
	* Override default start index.
	*****************************************************************************************************/
	function _startTokenId() internal pure override returns (uint256) {
		return 1;
	}

	/*****************************************************************************************************
	* Base URI for collection metadata.
	*****************************************************************************************************/

	function setBaseURI(string memory newBaseURI) external onlyOwner {
		baseURI = newBaseURI;
		emit BaseUriUpdated(baseURI);
	}

	function _baseURI() internal view override returns (string memory) {
		return baseURI;
	}

	/*****************************************************************************************************
	* Pause mint and transfers.
	*****************************************************************************************************/
	function pause() public onlyOwner {
		_pause();
	}

	/*****************************************************************************************************
	* Unpause mint and transfers.
	*****************************************************************************************************/
	function unpause() public onlyOwner {
		_unpause();
	}

	/*****************************************************************************************************
	* Before token transfer hook. Activate whenNotPaused check.
	*****************************************************************************************************/
	function _beforeTokenTransfers(
		address from,
		address to,
		uint256 startTokenId,
		uint256 quantity
	)
		internal
		whenNotPaused
		override(ERC721A)
	{
		super._beforeTokenTransfers(from, to, startTokenId, quantity);
	}

	/*****************************************************************************************************
	* Transfer From
	* @param from: from address
	* @param to: destination address
	* @param tokenId: tokenId to transfer
	*****************************************************************************************************/
	function transferFrom(
		address from,
		address to,
		uint256 tokenId
	)
		public
		whenNotPaused
		override(ERC721A)
	{
		super.transferFrom(from, to, tokenId);
	}

	/*****************************************************************************************************
	* Safe Transfer From
	* @param from: from address
	* @param to: destination address
	* @param tokenId: tokenId to transfer
	* @param data: additional data field
	*****************************************************************************************************/
	function safeTransferFrom(
		address from,
		address to,
		uint256 tokenId,
		bytes memory data
	)
		public
		whenNotPaused
		override(ERC721A)
	{
		super.safeTransferFrom(from, to, tokenId, data);
	}

	/*****************************************************************************************************
	 * @notice Stops minting. Once required amount of tokens are minted, minting will be stopped forever.
     * @dev Emits "MintingStatusChanged"
     *****************************************************************************************************/
	function endMinting()
		external
		onlyOwner
	{
		require(mintingAllowed, "MINTING_IS_ALREADY_STOPPED");
		mintingAllowed = false;
		emit MintingStatusChanged(false);
	}

	/*****************************************************************************************************
	 * @notice Sets royalty percentage for secondary sale
     * @dev Emits "RoyaltyPercentageChanged"
     * @param percentage The percentage of royalty to be deducted
     *****************************************************************************************************/
	function setRoyaltyPercentage(uint256 percentage)
		external
		onlyOwner
	{
		royaltyPercentage = percentage;
		emit RoyaltyPercentageChanged(royaltyPercentage);
	}

	/*****************************************************************************************************
	 * Get royalty amount at any specific price.
	 * @param price: price for sale.
     *****************************************************************************************************/
	function getRoyaltyInfo(uint256 price)
		external
		view
		returns (uint256 royaltyAmount, address royaltyReceiver)
	{
		require(price > 0, "PRICE_CAN_NOT_BE_ZERO");
		uint256 royalty = (price * royaltyPercentage)/100;
		return (royalty, owner());
	}

	/*****************************************************************************************************
	 * Mint NFT
	 * @param to: destination address.
	 * @param quantity: quantity to mint.
     *****************************************************************************************************/
	function mint(address to, uint256 quantity)
		public
		onlyOwner
		whenNotPaused
	{
		require(mintingAllowed, "MINTING_IS_STOPPED");
		_mint(to, quantity);
	}

	/*****************************************************************************************************
	 * Batch Mint NFTs
	 * @param to: array of destination addresses.
	 * @param amounts: array of quantities to mint to specific address.
     *****************************************************************************************************/
	function batchMint(address[] memory to, uint256[] memory amounts)
		public
		onlyOwner
		whenNotPaused
	{
		require(mintingAllowed, "MINTING_IS_STOPPED");
		require(to.length == amounts.length, "INVALID_DATA");
		for (uint256 i = 0; i < to.length; i = i + 1) {
			_mint(to[i], amounts[i]);
		}
	}

}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"uri","type":"string"}],"name":"BaseUriUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"status","type":"bool"}],"name":"MintingStatusChanged","type":"event"},{"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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"newPercentage","type":"uint256"}],"name":"RoyaltyPercentageChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"to","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"batchMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"endMinting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"name":"getRoyaltyInfo","outputs":[{"internalType":"uint256","name":"royaltyAmount","type":"uint256"},{"internalType":"address","name":"royaltyReceiver","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintingAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"royaltyPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newBaseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"percentage","type":"uint256"}],"name":"setRoyaltyPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]