import java.util.*;
import java.text.NumberFormat;     
import java.util.Locale;
import java.util.Random;           

public class NFTMarketPlace 
{
   //VARIABLES ARE GIVEN
   public static String rarity [] = {"Common","Uncommon","Rare","Epic","Legendary","Mythic"} ;
   private static double lowFloor = 0.5;
   private static double highFloor = 99999.99;
   private static String floorMssg = "Please enter in a value between $0.50 to $99,999.99: ";  
   private static int lowRarity = 1;
   private static int highRarity = 6;
   private static String rarityMssg = "Please enter in a value between 1 to 6" 
                              +"(NOTE all rational values will be truncated to the whole number): ";
   private static int lowToken = 1;
   private static int highToken = 2;
   private static String tokenMssg = "Please enter in a 1 for ERC-721 or a 2 for a BEP-721 token type"+
                           "(NOTE all rational values will be truncated to the whole number): ";  
   static Scanner sc = new Scanner(System.in);
   
   public static void main (String args [])
   {
      //STUDENT WILL MAKE THIS
      //Pre loaded customer data: students will only get the string literals
      NFTData client = new NFTData("Ana1234","Bored BPA Yacht Club");
      client.walletAddress.setAdd("1Awyd1QWR5gcfrn1UmL8dUBj2H1eVKtQhg");
      String yesNo= ""; 
      
      //STUDENT WILL MAKE THIS
      //Checks that the customer object was created 
      if(client != null && client.walletAddress != null)
         System.out.println("Welcome " + client.getUN()+ " to the NFT Market Place form."+ 
               "Your wallet is now connected (verify below):\n"+client.walletAddress.getAdd());
      
      //THIS IS GIVEN
      //Prompts the user to see if they want to update the record 
      do{
         System.out.print("\nType in \"Yes\" if you want create a new NFT:\nENTER: Yes or No: ");
         yesNo = getUserStringInput();    //helper method created by the student
         if(yesNo.equals("yes")|| yesNo.equals("y"))
         {
            setFloorPriceNFTDataRecord(client);   //helper method call given
            setNFTRarityRecord(client);
         }
      }while (yesNo.equals("yes") == false && yesNo.equals("no") == false && 
               yesNo.equals("y") == false && yesNo.equals("n") == false);
      
      //THIS IS GIVEN
      //Prompts the user to see if they want to retrieve the record 
      do{
         System.out.print("\nDo you want to see the profile for this user?\nENTER: Yes or No: ");
         yesNo = getUserStringInput();       //helper method created by the student
         if(yesNo.equals("yes")|| yesNo.equals("y"))
         {
            consoleRecordCheck(client);       //helper method call created by student
         }
         
         else if(yesNo.equals("no")|| yesNo.equals("n")){
            System.out.print("\nHave a great day and see you on the Moon!");
            System.exit(0);                  
         } 
      } while (yesNo.equals("yes") == false && yesNo.equals("no") == false && 
                  yesNo.equals("y") == false && yesNo.equals("n") == false);                 
   
   }
   //THIS IS GIVEN
   //Prompts the user to submit a floorPrice: calls other helper methods 
   private static void setFloorPriceNFTDataRecord(NFTData c)
   {
      System.out.println("\nAll new NFT's require a new Floor Price."+ 
                        "How much will be the NFT's floor price? ");
      double numberInput = getUserNumericalInput(lowFloor, highFloor, floorMssg);
      c.setFloorPrice(numberInput);
      setContractAddress(c);                        
       
   }
   //THIS IS GIVEN
   //Sets the rarity of the NFT
   //Students will need to make the get method to have user input for the NFT rarity value
   private static void setNFTRarityRecord(NFTData c)
   {
      System.out.println("\nAll new NFT's require a rarity. Choose the number for the level of rarity:\n"+ 
                          "(6)Mythic, (5)Legendary, (4)Epic, (3)Rare, (2)Uncommon, (1)Common");
      int rarityInt = (int)getUserNumericalInput(lowRarity, highRarity, rarityMssg);  
      c.setRarity(rarity[rarityInt-1]);      
   }
   
   //STUDENT WILL MAKE THIS
   //Creates and stores the reference ID (random letters and numbers) 
   //Object Needs to store eigther a ERC-721 or BEP-721 token. 
   //Address is four parts, x's are delimeters
   private static void setContractAddress(NFTData trader)
   {
      String referenceString = "";
      char randomReferenceLetter  = 'x';
      Random rand = new Random();
      int temp = 0;
      String token ="";
      
      do{
         
         temp = (int)getUserNumericalInput(lowToken, highToken, tokenMssg);
      
      }while(temp >2 || temp <1);
      if(temp == 1)
         token =  "ERC721";
      else token = "BEP721";
      // Blocks of four digit codes for the address name that is enclosed wiht 'x' as delimeters
      referenceString = trader.getUN().substring(0,3);   
      for (int i=0; i<4; i++)
      {
         int randomReferenceNumber = 0;
         do{ randomReferenceNumber = rand.nextInt(10000);
         } while(randomReferenceNumber<1000);
         referenceString += "x" + randomReferenceNumber + "x";
      }
      referenceString += token;
      System.out.print("Your NFT contract address: " +referenceString +"\n");
      trader.setNFTAddress(referenceString);
      
   }
   
   //STUDENT WILL MAKE THIS
   //Gets the user input for the yes or no prompts and turns it into LC 
   //helper method 
   private static String getUserStringInput()
   {
      String temp = sc.nextLine().toLowerCase();
      
      return temp;
   }  
   
  //STUDENT WILL MAKE THIS 
  //Gets use to input numerical responses. 
  //The return value is double for simplicity purposes. 
  //The return value will need to be cast to int where appropriate
  //An example is given in the initial code       
   private static double getUserNumericalInput(double low, double high, String message)
   {
      double temp;
      while(true){   
         try{
            do{
               System.out.print(message);
               temp = sc.nextDouble();
               sc.nextLine();
               temp = 0.01 * Math.floor(temp *100);
            }while(temp >high || temp <low);
            return temp;
            
         }
         catch(InputMismatchException e)
         {
            sc.next();
            System.out.println("\nPlease enter a correct value.");
         }
      }
      
   }


   //STUDENT WILL MAKE THIS
   //Prints the final record to the console by using data from the object 
   private static void consoleRecordCheck(NFTData c)
   {
      NumberFormat d = NumberFormat.getCurrencyInstance(new Locale("en", "US"));
      System.out.println("\n***************************"+
                           "****************************");
      System.out.println("******************* CREATOR RECORDS "+
                                          "*******************");
      System.out.println("\nUsername: "+ c.getUN());
      System.out.println("Wallet Address: " +c.walletAddress.getAdd());
      System.out.println("Collection Name: " +c.getCollection());
      if(c.getNFTAddress() != null)  //This will determine to print NFT information or not
      {
         System.out.println("NFT Address: " + c.getNFTAddress());
         System.out.println("Floor Price: " + d.format(c.getFloorPrice()));
         System.out.println("Rarity/Collection: " + c.getRarity());
      }
      System.out.println("\n*****************************"+
                              "**************************");
      System.out.println("*********************************"+
                                  "**********************");
   }
}



/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
/*****************NFTData*****************************/
/*Student will only get the .class files 
for the following object classes */
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
class NFTData 
{
   private String userName;
   private String productName;
   private String rarity;
   private String collectionName;
   private double floorPrice;
   private String tokenType;
   private String nftAddress = null;  
  
   
   public WalletAddress walletAddress;
   
   public NFTData (String un, String co)
   {
      this.userName = un;
      this.productName = null;
      this.rarity = null;
      this.collectionName = co;
      this.tokenType = null;
      this.floorPrice = 0;
      this.walletAddress = new WalletAddress();
      
   }
   //LONG VERSION NOT USED IN TEST
   public NFTData (String un, String pn, String ra, 
                  String co, String bc, Double fp)
   {
      this.userName = un;
      this.productName = pn;
      this.rarity = ra;
      this.collectionName = co;
      this.tokenType = bc;
      this.floorPrice = fp;
      this.walletAddress = new WalletAddress();
   }
   
   public String getUN()  //gets username
   {
      return this.userName;
   }
            
   public void setUN(String un)  //sets username
   {
      this.userName = un;
   }
   
   public String getPN()  //gets productname
   {
      return this.productName;
   }

   public void setPN(String pn)  //sets productname
   {
      this.productName = pn;
   }
   
   public String getRarity()  //gets the rarity
   {
      return this.rarity;
   }
      
   public void setRarity(String ra)  //sets rarity
   {
      this.rarity = ra;
   }
      
   public String getCollection()  //gets collection name
   {
      return this.collectionName;
   }
      
   public void setCollection(String co) //sets collection name
   {
      this.collectionName = co;
   }

   public Double getFloorPrice() //gets floorPrice
   {
      return this.floorPrice;   
   }
   
   public void setFloorPrice(Double f) //sets floorPrice amount
   {
      this.floorPrice = f;   
   }
      
   public String getTokenType()  //gets plate #
   {
      return this.tokenType;  
   }
    
   public void setTokenType(String bc)  //sets plate #
   {
      this.tokenType = bc;
   }
    
   public void setNFTAddress(String a)
   {
      
      nftAddress = a;
   }
      
   public String getNFTAddress()
   {
      return nftAddress;
    
   }

    
   public String toString() //not used; wrong result
   {
      return this.getClass().getName() + "WRONG " + " " + this.getUN() + "\n WRONG" + 
             this.getRarity() + " " + this.getCollection() +
            "\n WRONG" + this.getTokenType() + "\n WRONG" + this.getFloorPrice() + "]";
   }
} 
   
////////////////////////////////////////////////////
////////////////////////////////////////////////////
/*****************WalletAddress********************/
/*Student will only get the .class files for this */
////////////////////////////////////////////////////
////////////////////////////////////////////////////

class WalletAddress 
{
   private String publicKeyWallet;
      
   public WalletAddress()
   {
      this.publicKeyWallet = "NA";
   }     
   
   public WalletAddress(String a)
   {
      this.publicKeyWallet = a; 
         
   }
   public String getAdd()
   {
      return this.publicKeyWallet;
   }   
   
   public void setAdd(String s)
   {
      publicKeyWallet = s;
      
   }    
   
}  

