// File: src/GANLocator.sol



//SPDX-License-Identifier: UNLICENSED

// MWWWWMWWWWMWWWWMWWWMWWWWMWWWWMWWWWWWWWWWWWWWWNNWWNNNNWWWNWWWWWWMWWWWMWWWWMWWWWMWWWWMWWWWMWWWMWWWWMWW
// WWWMWWWMWWWWMWWWWMWWWWMWWWWWWWWMWWWWWWNNNWNNWWWWWWWWWWWNNNXNNWWWWWMWWWWWWWWWWWWWMWWWWMWWWWMWWWWWWWWW
// MWWWWWWWWWWWWWWWWWWWWWWWMWWWWMWWWWWWNNNWWWWWNXXKKKKKXXNWWWWNNNNNWWWWMWWWWWWWWWWWWWWWWWWWWWWWMWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNNWWWWN0kdolcc::::::clodk0XWWWNNXNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNNWWWNOdl:;::::::::::::;;;;:cdOXWWNXXNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNWWWXkl:::ccccllllcccc::::;;;;;;cxKWWNXXNWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWMWWWWMWWWWWWWWWWNNWMNkc;::clloooolllllllcc:::;;;;;;;cxXWWXXNWWWWWWWWWWWWWMWWWWMWWWWWWWWW
// MWWWWMWWWWWWWWWWWWWWWWWWWWWNNWWKo;;::cldkO0Oxdooolllllcc:;;;;;;;;;oKWWXKNWWWWWMWWWWMWWWWWWWWWWWWWMWW
// WWWMWWWWWWWWWWWWWMWWWWMWWWNNWMKo;;::clokKXXKkdooolllllcc::;;;;;;;;;l0WWXKXWWWWWWMWWWWMWWWWMWWWWMWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWNWMNd;;:::ccldkO0Oxooollllllcc::;;,,,;;;;;oXMWKXNWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWNNMWO:;;;:::cclooooolllllllcccc::;;,,,,;;;;;kWMXKXWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWNNWMNd;;;;;:::cccccllllllcccccc::;;;,,,,;;;;;oXMNKKWWWWWWWWWWWWWWWWWWWWWWWWW
// MWWWWWWWWWWWWWWWWWWWWWWWWNWMXo,;;;;;::::ccccccccccccc::::;;,,,,,,;;;;lKMNKKNWWWWWWWWWWWWWWWWWWWWWMWW
// WWWWWWWMWWWWMWWWWMWWWWWWNXWMNo;;;;;;;;:::::::::::::::::;;;,,,,,,,;;;;lXMN0KNWWWWMWWWWMWWWWMWWWWMWWWW
// MWWWWMWWWWMWWWMWWWWMWWWWWNNMWx;;;;;;;;;;;;:::::::::;;;;;,,,,,,,,;;;;;dNMN0XNWWMWWWWMWWWWWWWWWWWWWMWW
// WWWWWWWWWWWWWWWWWWWWWWWWWNNWW0c;;;;;,;,,;;;;;;;;;;;;;,,,,,,,,,,,;;;;c0WWK0XWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWNXNWWk:;;;;;,,,,,,,,,,,,,,,,,,,,,,,,,,;;;;:xNMN0KNWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWNNWMNk:;;;;;,,,,,,,,,,,,,,,,,,,,,,,;;;;;:xNMNKKNWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWNNWWWOl;;;;;;,,,,,,,,,,,,,,,,,,,;;;;;;cONMN0KXNWWWWWWWWWWWWWWWWWWWWWWWWWW
// MWWWWMWWWWMWWWWWWWWWWWWWMWWWNXNWWXxc;;;;;;;;,,,,,,,,,,;;;;;;;;;cxKWWX00XWWWWWWMWWWWMWWWWWWWWWWWWWMWW
// WWWMWWWMWWWWWWWWWMWWWWMWWWWWWNXXNWWXkl:;;;;;;;;;;;;;;;;;;;;;:lxKWWNK0XNWWWWWMWWWMWWWWMWWWWMWWWWMWWWW
// MWWWWWWWWWWWWWWWWWWMWWWWMWWWWWWNXXNWWN0xoc:;;;;;;;;;;;;;:cox0NWWNK0KNWWWWMWWWWWWWWWWWWWWWWWWMWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNXXXNWWWNKkc;:ccllllllxKXWWWNK00XNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNXXXXNWMXocoxOO000OkXMWXK0KXXNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWXXWMXocoxO0000OkXMWK0XNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWMWWWWMWWWWWWWWWWWWWWWWWWWWWNNWMXocokO0000OkXMWK0NWWWWWWWWWWWWWWWWWWWWWWWWMWWWWMWWWWWWWWW
// MWWWWMWWWWMWWWMWWWWMWWWWMWWWWMWWWWMWWWWNNWMXocdkO0KKKOkXMWK0NNWWWWWWMWWWWMWWWWMWWWWMWWWMWWWWMWWWWMWW
// WWWWWWWWWWWWMWWWWMWWWWWWWWWWWWWMWWWWWWWNNWMXocdkO0KKKOkXMWK0NWWWWWMWWWWWWWWWWWWWWWWWWMWWWWMWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNNWMXocokO0KKKOkXMWK0NWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNNWMXocokO0KKKOkXMWK0NWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNNWMXocokO0KKKOkXMWK0NWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNNWMXocokO0KKKOkXMWK0NWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWMWWWMWWWWMWWWWMWWWWWWWWWMWWWMWWWWMWWNNWMXocokO00KKOkXMWK0NWWWWWMWWWMWWWWWMWWWMWWWWMWWWWMWWWWMWWWW
// MWWWWMWWWWMWWWWWWWWWWWWWMWWWWMWWWWWWWWWNNWMXocokO00KKOkXMWK0NWWMWWWWMWWWWMWWWWMWWWWMWWWWWWWWMWWWWMWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNNWMXocokO00KKOkXMWK0NWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNNWMXocokO00KKOkXMWK0NWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNNWMXocokO00KKOkXMWK0NWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNNWMXocokO00KKOkXMWK0NWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// MWWWWMWWWWMWWWMWWWWWWWWWMWWWWMWWWWMWWWWNNWMXocokO00KKOkXMWK0XNWMWWWWMWWWWMWWWWMWWWWMWWWWWWWWWWWWWMWW
// WWWWWWWMWWWWMWWWWMWWWMWWWWWWWWWMWWWWMWWNNWMXocokO00KKOkXMWK0NWWWWWMWWWMWWWWWWWWWMWWWWMWWWWMWWWWMWWWW
// MWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNNWMXocokO00KKOkXMWK0NWWWWWWWMWWWWWWWWWWWWWWWWWWWWWWWWWWWWMWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNNWMXocokO00KKOkXMWK0NWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNNWMXocokO00KKOkXMWK0NWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNNWMXocdkO0KKKOkXMWK0NWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWMWWWWMWWWWWWWWWWWWWWWWWWWWWWWWWWNNWMXocdkO0KKKOkXMWK0NWWWWWWWWWWWWWWWWWWWMWWWWMWWWWMWWWWWWWWW
// MWWWWMWWWWMWWWWWWWWMWWWWMWWWWMWWWWWWWWWNNWMXocokO0KKKOkXMWK0XWWWWWWWMWWWWMWWWWMWWWWWWWWWWWWWMWWWWMWW
// WWWWWWWWWWWWMWWWWMWWWWWWWWWWWWWWWWWWMWWNNWMNkodkO0KKK00NMWK0NWWWWWMWWWWWWWWWWWWWWWWWWMWWWWMWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNNWMWNNNNNWWWWWWNKKXNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNXXXNNNNNNNNXXKKKXNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNXXXXXXXXXXXXNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
// MWWWWMWWWWMWWWMMWWWMMWWWMWWWWMWWWMMWWWMMWWWMWNNWMWWNNWMWWWMMWNWMMWWWMWWWWMWWWWMWWWMMWWWMMWNWMMWWWMMW
pragma solidity ^0.8.15;

//Solmate contract used for managing contract ownership.
import "solmate/auth/Owned.sol";

//Interface allowing contract to interact with PokeGAN NFT contract and NFTx LP token contract.
interface IERC20ERC721 {
   function ownerOf(uint256 tokenId) external view returns (address owner);
   function balanceOf(address account) external view returns (uint256);
}

contract GANLocator is Owned {
   
   //Address store for PokeGAN contract.
   address immutable PokeGAN;
   //Address store for xKOPEWETH (1) LP token contract.
   address immutable GANLP1;
   //Address store for xKOPEWETH (2) LP token contract.
   address immutable GANLP2;

   //Constructor initializing PokeGAN and GANLP contracts as well as
   constructor(
      address _PokeGAN,
      address _GANLP1,
      address _GANLP2
   ) Owned  (
      msg.sender
   )  {
      PokeGAN = _PokeGAN;
      GANLP1 = _GANLP1;
      GANLP2 = _GANLP2;
   }
   
   //Modifier utilized by non-owner locations setting functions to cheeck if location setting is active.
   modifier active {
      require(GANLocationSettingActive);
      _;
   }

   //Boolean value to determine if location setting is active.
   bool public GANLocationSettingActive;
   
   // Mapping to store the value of locations set using token IDs.
   mapping (uint => string) public GANLocationWithGAN;
   
   // Mapping to store the value of locations set using LP.
   mapping (address => string) public GANLocationWithLP;
    

   // Set one global location per token ID that you wallet holds. You may update this location as long as the setting of locations is allowed.
   // @param _tokenId The token ID of the token you wish to set a location for.
   // @param _location The location you wish to set for the token represented in 2 x/y coordinates forming a rectangle.
   function setLocationWithGAN(uint _id, string calldata _location) active external {
      require(IERC20ERC721(PokeGAN).ownerOf(_id) == msg.sender, "You are not the owner of this token.");
      GANLocationWithGAN[_id] = _location;
   }

   // Set one global location per wallet address as long as that wallet is holding LP tokens from one of the NFTx pools.
   // @param __location The lcoation you wish to set for the wallet in which you hold LP, represented in 2 x/y coordinates forming a rectangle.
   function setLocationWithLP(string calldata _location) active external {
      require(IERC20ERC721(GANLP1).balanceOf(msg.sender) > 0 || IERC20ERC721(GANLP2).balanceOf(msg.sender) > 0, "You do not have any GAN LP tokens.");
      GANLocationWithLP[msg.sender] = _location;
   }

   // Owner only function to flip the state of location setting.
   function flipLocationSettingState() external onlyOwner {
      GANLocationSettingActive = !GANLocationSettingActive;
   }

   // Owner only function to modify the value of a location set using a token ID.
   function executiveGANLocationWithGANSetting(uint _id, string calldata _location) external onlyOwner {
      GANLocationWithGAN[_id] = _location;
   }

   // Owner only function to modeify the value of a location set using NFTx LP tokens.
   function executiveGANLocationWithLPSetting(address _address, string calldata _location) external onlyOwner {
      GANLocationWithLP[_address] = _location;
   }

}
// File: lib/solmate/src/auth/Owned.sol



// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event OwnerUpdated(address indexed user, address indexed newOwner);

    /*//////////////////////////////////////////////////////////////
                            OWNERSHIP STORAGE
    //////////////////////////////////////////////////////////////*/

    address public owner;

    modifier onlyOwner() virtual {
        require(msg.sender == owner, "UNAUTHORIZED");

        _;
    }

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(address _owner) {
        owner = _owner;

        emit OwnerUpdated(address(0), _owner);
    }

    /*//////////////////////////////////////////////////////////////
                             OWNERSHIP LOGIC
    //////////////////////////////////////////////////////////////*/

    function setOwner(address newOwner) public virtual onlyOwner {
        owner = newOwner;

        emit OwnerUpdated(msg.sender, newOwner);
    }
}