/*
Online Java - IDE, Code Editor, Compiler

Online Java is a quick and easy tool that helps you to build, compile, test your programs online.
*/

import java.util.*;

//With respect to my previous coding examples using Statistic calculators, I have passed the permutation or combination number
//argument to parameter in constructor of the main application.
//I want to attempt this challenge without modifying the signature if possible
//This will be only way it will meet exact requirements
//I am also performing this action since I feel that there are basic requirements with
//Permutations Calculator nPr for this challenge.
//We are only utilising P(p.length(), p.length()
//Hence the focus will remain on the anagram loops.

//Also this time, we do not need to go through the pos for loop. Since in the previous example, we were going through 
//each Character in String p and eliminating it from the StringBuilder if it did appear in String S (within same block size).
//The fact that we have created this permutation means that requirement is to find palindrome exactly as it appears in String s.

public class Main 
{
    static long permutations;
    
    public static void main(String[] args) 
    {
        //String p="abc";
        //String s="cbaebabacd";
        
        String p="abc";
        String s="cbaebabacd";
        
        
        
        System.out.println("Welcome to Online IDE!! Happy Coding :)");
        int originalNumber=p.length();
        int n=originalNumber;
        int r = p.length();
        
        Map <Integer, Long> m = new HashMap<>();
        
        Permutation perm = new Permutation();
        n=originalNumber;
        //(int n, int r, int originalNumber, Map factorialResults)
        perm.Permutations (n,r,originalNumber, m);
        //n=originalNumber;
        
        System.out.println("HERE");
        permutations = perm.getPermutations();
       
        
        //String p;
        //String s;
        
        //TEST CASE 1:
        findAnagrams(s,p);
        
        //TEST CASE 2:
        //findAnagrams("abab", "ab");
        
        //TEST CASE 3:
        //findAnagrams("azazazazazazzzzaaazazazaz", "az");
        
        //TEST CASE 4:
        //findAnagrams("azazazazazazzzzaaazazazpp", "az");
        
        
    }
    
    public static void findAnagrams(String s, String p)
    {
        Set <Integer> stRandomNums = new HashSet<>();
        int pos=0;
        int subsetNumber=1;
        Set <String> st = new HashSet<>();
        StringBuilder sb = new StringBuilder(p);
        int startPos=0;
        boolean hasCharFound=false;
        int counter=0;
        StringJoiner sj;
        int temp1;
        Random rand = new Random();
        String[] valuesSet; 
        String []backupValuesSetBeforeModification;
        int num;
    int count=0;
    int subsetEntry=1;
    int cycles=0;
    int totalcycles=0;
    int difference = 0;
    List <String> backupValuesSet = new ArrayList<>();
    int currentSetSize;
    int newSetSize;
    int n;
    
    //I did try to experiment with creating a character array and trying to add it into List
    //but Java did not like the syntax 
    //List <Character> lst = new ArrayList<Character>(Arrays.asList(p.toCharArray()));
    
    //NO ISSUES TRYING IN THIS CONVENTION
    //List <String> lst = new ArrayList<String>(Arrays.asList("test"));
    
    //List <Character> lst = new ArrayList<Character>();
    
    //So I have adopted more convention approach.
    //My instinct tells me using streams or possibly lamba would do this much more efficiently.
    //The knowledge is still above my capacity so I will attempt as such
    //for (char c: p.toCharArray())
    //{
        
     //   lst.add(c);
    //}
        
        System.out.println("String (s) to search in: " + s);
        System.out.println("String (p) template word: " + p);
        
        if (s.length()<p.length())
        {
            System.out.println("template word is longer length than main String");
            System.exit(0);
        }
        
        //at this point, it can call the permutation constructor
        //it can perform P(3,3) for instance
        //this will determine how many times to perform operation.
        //in terms of populating the hashSet with permutations.
        //it can perhaps obtain this and return this String (this will be permutation of p)
        //it would then assign the permutation to the StringBuilder
        

        //---------------------------------------------

            System.out.println("*************INITIAL VALUE OF  CYCLES: " + cycles);
        
        
        
        do
        {
            sj=new StringJoiner("");
            
                for (int m=0;m<p.length();m++)
                {
                    //System.out.println("list size: " + lst.size());
                   
                    temp1 = rand.nextInt(p.length());
                    currentSetSize=stRandomNums.size();
                    stRandomNums.add(temp1);
                    if (m==0)
                    {
                        System.out.println("HERE");
                        System.out.println(currentSetSize);
                        System.out.println(stRandomNums.size());
                        System.out.println("random num: " + temp1);
                    sj.add(Character.toString(p.charAt(temp1)));
                    }
                    else
                    {
                        
                    if (stRandomNums.size()==currentSetSize)
                    {System.out.println("HER1");
                        m=m-1;
                    }
                    else
                    {
                        System.out.println("random num: " + temp1);
                    sj.add(Character.toString(p.charAt(temp1)));
                    }
                    }
                    
                    
                    
                }
                
                stRandomNums.clear();
                 
                
                
                    System.out.println("\n");
                    currentSetSize=st.size();
                    st.add(sj.toString());
                    sj=new StringJoiner("");
                    newSetSize = st.size();
                    cycles++;
                    totalcycles++;
            
           System.out.println("end\n");
        }while (newSetSize<permutations);

        valuesSet = st.toArray(new String[st.size()]);
        backupValuesSetBeforeModification = st.toArray(new String[st.size()]);
        
        System.out.println("******************Contents of the backup set");
        System.out.println("******************Contents of the valuesSet");
        
        for (String g: valuesSet)
        {
            System.out.println("Subset " + subsetNumber+": " + g);
            subsetNumber++;
        }
        
        subsetNumber=1;
        
        for (String m: backupValuesSet)
        {
            n=0;
            do
            {
                            
                n++;
                
            }while (n<valuesSet.length);
            
        }  //end for processing backupValuesSet
        
        System.out.println("*************NEW VALUE CYCLES: " + cycles);
        System.out.println("*************RUNNING TOTAL CYCLES: " + totalcycles);
        
        System.out.println("***PROCESSING SET AT INDEX: " + (difference));
        System.out.println("**ENDING AT INDEX:***** " + st.size() +"\n");
        
        backupValuesSet= new ArrayList<>(Arrays.asList(backupValuesSetBeforeModification)); 
        
        for (int entry=0; entry<valuesSet.length; entry++)
        {
            if (valuesSet[entry]!="ALREADY PROCESSED")
            {
                System.out.println(valuesSet[entry] + "    \n\nSubset: " + subsetEntry  + "  at cycle number: " + totalcycles);
                
                subsetEntry++;
            
                //MAIN LOGIC OF THE NEW CODE OFFICIALLY STARTS HERE.
                
                sb=new StringBuilder(valuesSet[entry]);
                System.out.println("THIS IS SB: " + sb.toString());
                
                    //setting the startPos as 0 has permitted it entry back into the while loop
                  while(p.length()+startPos<s.length())
        {
            do
            {
              
                
               startPos=counter;
            
                for (int i=startPos; i<s.length();i++)
                {
                    if(!sb.toString().isEmpty())
                    {
                        System.out.println("\nThis is STARTPOS: " + startPos);
                        System.out.println("This is sb length: " + sb.length());
                        System.out.println("This is s length: " +  s.length());
                    }
                
                    //for (int pos=0; pos<=sb.length(); pos++)
                    //{
                        if (hasCharFound)
                        {
                            pos=0;
                        }
                        if (!sb.toString().isEmpty())
                        {
                            System.out.println("value of pos: " + pos);
                            System.out.println("value of sb: " + sb.toString());
                            System.out.println("Checking character: " + sb.toString().charAt(pos) + 
                            "  against the main String index: " + i + "("+s.charAt(i)+")");
                    
                            System.out.println("SUBSTRING EXAMINED: " + s.substring(startPos,(startPos+p.length())));
                            
                            //now the focus is on checking to see if the character of String p appears in that order in block size in String s
                            if (Character.toString(s.charAt(i)).indexOf(sb.toString().charAt(pos))==0)
                            {
                                System.out.println("char found: " + sb.toString().charAt(pos) + 
                                "    at index: " + i);
                               
                                System.out.println(sb.toString().charAt(pos) + " has been removed from StringBuilder (String p)" +  "= "+ sb.toString());
                                sb.deleteCharAt(pos);
                                System.out.println("This is current StringBuilder (String p): " + sb.toString());
                                hasCharFound=true;
                            }
                            else
                            {
                                System.out.println("NO MATCH FOUND");
                                pos=p.length();
                                System.out.println("StringBuilder being emptied: " + sb.toString());
                                sb.delete(0,sb.length());
                                hasCharFound=false;
                                break;
                            }
                        }
                        
                         pos++;
                         if (pos==p.length())
                        {
                            pos=0;
                            break;
                        }
                    //}
                }
            }while(!sb.toString().isEmpty());
        
            if (sb.toString().isEmpty() && hasCharFound)
            {
                System.out.println("**********************************************************");
                System.out.println(s.substring(counter,(counter+p.length())) + " is an anagram of: " + p 
                + "\t\t\tIndex("+counter+")");
                System.out.println("**********************************************************");
            }
            System.out.println("*****RESTORING BACKUP OF STRINGBUILDER (String p): " + valuesSet[entry]);
            
            pos=0;
            sb=new StringBuilder(valuesSet[entry]);
            hasCharFound=false;
            counter++;
        
        } //end of while loop  while(p.length()+startPos<s.length())
        
          //but we will find that counter is still one greater than startPos in which the while loop terminated
        // so effectively, startPos will once again become 8.
        //and for a main String s where the length is 10 characters, this will invalidate the situation and generate a
        //StringIndexOutOfBoundsException
        //effectively I have set the counter =0  once it exits the while loop.
        //we know at this point it is in the for loop where it is processing the permutations.
        //I believe all the conditions are now set for a fresh execution....
        
        counter=0;
        startPos=0;
        
        
        
                
            }
        }
        difference = newSetSize;
    }  //end of constructor...

//-----------------------------------------------------------------

      
    }
    
    
    
    class Permutation
{
    static long result=0;
    static int n;
    static int r;
    
    public long getPermutations()
    {
         System.out.println("***PERMUTATIONS***");
        System.out.println("P(n,r) = n! / (n−r)!");
        System.out.println("P(" + n+","+r+") = " + n+"!" + " / " + "("+n+"-"+r+")!");
        System.out.println(result);
    return result;
    }
     
    public static long Permutations (int n, int r, int originalNumber, Map factorialResults)
    {
        Permutation.n=n;
        Permutation.r=r;
       
        
        // n are objects
        // r is sample
        /*
        ***CALCULATION***
        P(n,r) = n! / (n−r)!
        */
        
        int temp;
        int denominator;
        
        if (originalNumber<r || r<0)
        {
            System.out.println("please enter n ≥ r ≥ 0");
            System.exit(0);
            
            return 0;
        }
        if (n>=1)
        {
            // EXAMPLE
            // P (5,6) = 5* 4 * 3 * 2 * 1 / (6-5)! = 24 / 2! = 24 / 2 * 1 = 24/2 = 12
            result = (n* (Permutations (n-1, r,originalNumber, factorialResults))); // this completes factorial for numerator
            factorialResults.put(n,result);
            
            if (n==originalNumber)
            {
                denominator = originalNumber-r;
                if (factorialResults.containsKey(denominator))
                {
                    factorialResults.get(denominator);
                    return result / (long)factorialResults.get(denominator);
                    }
                }
                return result;
                }
            return 1;
        }
    }