/*
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.*;

public class CentreJustified
{
    static int k=16;
    static int centrePadding=0;
    static int buffer=0;
    static int halfExtraPaddingBetweenWords=0;
    static boolean evenBuffer=false;
    static String paddingTest = "·";
    static int lengthLastLine=0;
    static StringBuilder sb=new StringBuilder();
    static String lineBeforeLastWord="";
    static int totalExtraPaddingBetweenWords=0;
    
    public static void createCentrePadding()
    {
        centrePadding = buffer;
        if (buffer%2==0)
        {
            halfExtraPaddingBetweenWords=centrePadding/2;
            evenBuffer=true;
        }
        else
        {
            if (buffer>1)
            {
                halfExtraPaddingBetweenWords=(centrePadding-1)/2;
            }
            else
            {
                totalExtraPaddingBetweenWords=1;
            }
        }
    }//end of method
    
    public static void applyCentrePadding(int textLength)
    {
        if (evenBuffer)
        {
            for (int b=0; b<halfExtraPaddingBetweenWords; b++)
            {
                sb.insert(0,paddingTest);
                sb.insert(sb.length(),paddingTest);
                System.out.println("Your line getting bigger:" + sb.toString() +  "(" + sb.length() + " chars inc white space will NOT exceed " + k + ")");
            }  
        }  //end of if(evenBuffer)
        else
        {
            if (totalExtraPaddingBetweenWords==1)
            {
                sb.insert(textLength,paddingTest);
                System.out.println("Your line getting bigger:" + sb.toString() +  "(" + sb.length() + " chars inc white space will NOT exceed " + k + ")");
                totalExtraPaddingBetweenWords=0;
            }
            else
            {
                for (int b=0; b<halfExtraPaddingBetweenWords; b++)
                {
                    sb.insert(0,paddingTest);
                    sb.insert(sb.length(),paddingTest);
                    System.out.println("Your line getting bigger:" + sb.toString() +  "(" + sb.length() + " chars inc white space will NOT exceed " + k + ")");
                }
                sb.insert(sb.length(),paddingTest);
                System.out.println("Your line getting bigger:" + sb.toString() +  "(" + sb.length() + " chars inc white space will NOT exceed " + k + ")");
            }
        }
        evenBuffer=false;
    }//end method
    
    public static void main(String[] args) 
    {
        System.out.println("Welcome to Online IDE!! Happy Coding :)");
        String text = "The quick brown fox jumps over the lazy dog";  // no issues.....
        //String text="";   // no issues
        //String text = " This is a test, but making it a bit longer!";  //no issues....
        //String text = "My";   //no issues
        //String text = "      My name is Amit Amlani. This is a sligthly longer test to see if the text can be spanned across multiple lines.";
        //String text = "  Some blank now            but there should be extreme amount on start second line";
        //String text = "This will be 16.";   //no issues.
        //String text = "This will be 16. Amit";  //no issues....
        //String text = "Thiswillbetesting  16 testing.";  //no issues
        //String text = "Java is a high-level, class-based";  // no issues...
        //String text="Java is a high-level, class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible. It is a general-purpose programming language intended to let programmers write once, run anywhere (WORA),[16] meaning that compiled Java code can run on all platforms that support Java without the need to recompile.[17] Java applications are typically compiled to bytecode that can run on any Java virtual machine (JVM) regardless of the underlying computer architecture. The syntax of Java is similar to C and C++, but has fewer low-level facilities than either of them. The Java runtime provides dynamic capabilities (such as reflection and runtime code modification) that are typically not available in traditional compiled languages.";
        
        String lastLine="";
        String tokentoString="";
        String line;
        int wordCount=0;  
        int lineLength;
        int lengthLineBeforeLastWord;
        String completeLine="";
        String HalfTotalExtraPaddingBetweenWords="";
        int extraPaddingBetweenWords=0; 
        boolean conditionOncePerLine=true;
        String truncatedWord="";
        String delimiter=" ";
        int wordsIntoLineAfterTruncation=0;
        int completeLinelength=0;
        int newposText=0;
        String existingFrontalPadding="";
        String existingFrontalPaddingTest="*";
        int existingFrontalPaddingCount=0;
        String[] completedLineRepository = new String[1000];
        int num=0;
        StringJoiner sj = new StringJoiner(paddingTest);
        int tokenLength=0; 
        StringTokenizer st = new StringTokenizer(text, delimiter);
        String temp=""; 
        StringTokenizer st1; 
        String temp1;  
        StringTokenizer st2;
        String temp2; 
        String alternateToken=""; 
        
        System.out.println("Original Text: " + text +"\n");
        
        for (int h=newposText; h<text.length(); h++)
        {
           if (text.charAt(h)==' ')
           {
               existingFrontalPadding = existingFrontalPadding + existingFrontalPaddingTest;
               existingFrontalPaddingCount++;
           }
           else
           {
               newposText=h;
               break;
            }
        }
        while (st.hasMoreTokens())
        {
            if (truncatedWord!="")
            {
                sb.append(truncatedWord);
                sj.add(sb);
                truncatedWord="";
                sb.delete(0,sb.length());
                wordsIntoLineAfterTruncation++;
            }
            temp=st.nextToken();
            tokentoString = temp.toString();
            tokenLength=tokentoString.length();
            
            if (wordCount==0)
            {
                sb.append(existingFrontalPadding);
                sb.append(tokentoString);
                alternateToken= existingFrontalPadding + tokentoString;
            }
            
            wordCount++;
            
            if ((tokenLength + existingFrontalPaddingCount) >k)
            {
                System.out.println("The following word exceeds line limit of k" + "(" + k + "):" + (temp));
                System.exit(0);
            }
            sb.delete(0,sb.length());
            
            if (wordCount>0)
            {
                sb.append(tokentoString);  
            }
            
                lineBeforeLastWord = sj.toString(); 
            
            if (existingFrontalPadding=="")
            {
                sj.add(sb);
            }
            else
            {
                System.out.println("Your existing frontal padding:"+existingFrontalPadding);
                sj.add(alternateToken);
                System.out.println("This is the token chosen:" + alternateToken);
            }
            existingFrontalPadding="";
            sb.delete(0,sb.length());
            line = sj.toString();  
            lineLength=line.length();
            wordsIntoLineAfterTruncation++;
            System.out.println("Your line getting bigger:" + line + "(" + lineLength + " chars inc white space)");
            System.out.println("Words after truncation: " + wordsIntoLineAfterTruncation);
            
            if (lineLength==k)
            {
                completeLine = line;
                completedLineRepository[num]=line;
                num++;
                completeLinelength=completeLine.length();
                System.out.println("Completed line:" +line);
                sj=new StringJoiner(paddingTest);
                wordsIntoLineAfterTruncation=0;
                HalfTotalExtraPaddingBetweenWords="";
                sb.delete(0,sb.length());
                tokentoString="";
                temp="";
                
                System.out.println("NEW LENGTH of line:" + completeLinelength);
            }
            if (lineLength>k)   
            {
                lengthLineBeforeLastWord= lineBeforeLastWord.length();
                System.out.println("Rolled back to(due to exceeding " + k +"):" + lineBeforeLastWord);
                System.out.println("Length rolled back line: " + lengthLineBeforeLastWord);
                truncatedWord=temp;
                System.out.println("This word getting truncated:" + truncatedWord);
                wordsIntoLineAfterTruncation--;
                buffer = k-lengthLineBeforeLastWord;
                System.out.println("The current buffer is: " + buffer);
                System.out.println("Number words to accomodate for: " + wordsIntoLineAfterTruncation + "("+ lineBeforeLastWord+")");
                System.out.println("Last word in tokenizer should be same as truncated word: " + temp);
                System.out.println("What is wordcount here: " + wordCount);
                System.out.println("What is truncated word count: " + wordsIntoLineAfterTruncation +"(" + lineBeforeLastWord +")  " + lengthLineBeforeLastWord + " chars" );
                System.out.println("Value of temp:" + temp);
                
                if (buffer>0)
                {
                    sj = new StringJoiner(paddingTest);  //resets StringJoiner....
                    completeLine="";
                    
                    try
                    {
                        if (buffer%(wordsIntoLineAfterTruncation-1)==0 && wordsIntoLineAfterTruncation>1)
                        {
                            createCentrePadding();
                            System.out.println("CURRENT LENGTH of line: " + lengthLineBeforeLastWord);
                            System.out.println("Qualified for extra padding");
                            System.out.println(lineBeforeLastWord + "   =>qualifies for " + halfExtraPaddingBetweenWords + " padding at front and " + (halfExtraPaddingBetweenWords+totalExtraPaddingBetweenWords) + " at end since it has:" +  wordsIntoLineAfterTruncation + " words");
                
                            applyCentrePadding(lengthLineBeforeLastWord);
                            st1=new StringTokenizer(lineBeforeLastWord, paddingTest); 
                            
                            while (st1.hasMoreTokens())
                            {
                                temp1=st1.nextToken();
                                sj.add(temp1);
                                sb.append(sj);
                                createCentrePadding();
                                line=sj.toString();
                                applyCentrePadding(line.length());
                                completeLine=sb.toString();
                                sb.delete(0,sb.length());
                            }
                            System.out.println("NEW LENGTH of line after formatting: " + completeLinelength);
                        }
                        else
                        {
                            if (temp!="")
                            {
                                createCentrePadding();
                                centrePadding=buffer;
                                System.out.println(lineBeforeLastWord + "   =>qualifies for " + halfExtraPaddingBetweenWords + " padding at front and " + (halfExtraPaddingBetweenWords+totalExtraPaddingBetweenWords) + " at end since it has:" +  wordsIntoLineAfterTruncation + " words");
                                sb.append(lineBeforeLastWord);
                                System.out.println("CURRENT LENGTH of line: " + lengthLineBeforeLastWord);
                
                                applyCentrePadding(lengthLineBeforeLastWord);
                                completeLine = sb.toString();
                                completeLinelength=completeLine.length();
                                System.out.println("NEW LENGTH of line after formatting: " + completeLinelength);
                                sj.add(temp);
                            }
                        }//end of else
                    }// end of try
                    catch (ArithmeticException e)
                    {
                        if (temp!="")
                        {
                            centrePadding=buffer;
                            System.out.println(lineBeforeLastWord + "   =>qualifies for " + halfExtraPaddingBetweenWords + " padding at front and " + (halfExtraPaddingBetweenWords+totalExtraPaddingBetweenWords) + " at end since it has:" +  wordsIntoLineAfterTruncation + " words");
                            sb.append(lineBeforeLastWord);
                            System.out.println("CURRENT LENGTH of line: " + lengthLineBeforeLastWord);
                            createCentrePadding();
                            applyCentrePadding(lengthLineBeforeLastWord);
                            completeLine = sb.toString();
                            completeLinelength=completeLine.length();
                            System.out.println("NEW LENGTH of line after formatting: " + completeLinelength);
                            sj.add(temp);
                
                        }  //end of if  (temp!="")
                    } //end of catch
                    
                    System.out.println("Completed line:" +completeLine);
                    sj=new StringJoiner(paddingTest);
                    wordsIntoLineAfterTruncation=0;
                    HalfTotalExtraPaddingBetweenWords="";
                    sb.delete(0,sb.length());
                    completedLineRepository[num]=completeLine;
                    num++;
                    System.out.println("This word will be carried over to next line:" + temp +"\n");
                }  //end of if buffer is greater than 0
            }  //end of if linelength is greater than k
        }   //end while (has more tokens)
        
        lastLine=sj.toString();
        System.out.println("Last token processed:" + temp);
        System.out.println("***Currently in last line:" + lastLine);
        System.out.println("***************************");
        
        if (lastLine=="")
        {
            lastLine=temp;
        }
        System.out.println("Finally completing the last line:" + lastLine);
        lengthLastLine = lastLine.length(); 
        
        if (temp!="")
        {
            try
            {
                while (!st.hasMoreTokens())
                {
                    if (wordsIntoLineAfterTruncation==0 && wordCount>0)
                    {
                        wordsIntoLineAfterTruncation++;
                    }
                    System.out.println("Left over StringJoiner: " + wordsIntoLineAfterTruncation + " word(s)=>" +  lastLine + "  (" + lengthLastLine + " chars inc white space)");
                    System.out.println("Total running words: " + wordCount);
                    buffer=k-lengthLastLine;
                    System.out.println("Buffer is: " + buffer);
           
                    if ((buffer%(wordsIntoLineAfterTruncation-1)==0 && wordsIntoLineAfterTruncation>1) )
                    {
                        createCentrePadding();
                        System.out.println(lastLine + "   =>qualifies for " + halfExtraPaddingBetweenWords + " padding at front and " + (halfExtraPaddingBetweenWords+totalExtraPaddingBetweenWords) + " at end since it has:" +  wordsIntoLineAfterTruncation + " words"); 
                        applyCentrePadding(lengthLastLine);
                        st2=new StringTokenizer(lastLine, paddingTest);
                        sj = new StringJoiner(paddingTest);
                    
                        while (st2.hasMoreTokens())
                        {
                            temp2=st2.nextToken();
                            sj.add(temp2);
                        }
                        sb.delete(0,sb.length());
                    
                        if (conditionOncePerLine)
                        {
                            sb.append(sj);
                            line=sj.toString();
                            createCentrePadding();
                            applyCentrePadding(line.length());
                            completeLine=sb.toString();
                            conditionOncePerLine=false;   //set flag to false so it does not re-appear until set to true above...
                        }
                    }   //end if checking if multiple words and buffer can be divided inter-word....
                    else
                    {
                        if (wordCount>0)
                        {
                            System.out.println("There is one word in last line:" + temp);
                            System.out.println("CURRENT LENGTH of line: " + tokenLength);
                            sb.append(lastLine);
                            System.out.println(lastLine + "   =>qualifies for " + halfExtraPaddingBetweenWords + " padding at front and " + (halfExtraPaddingBetweenWords+totalExtraPaddingBetweenWords) + " at end since it has:" +  wordsIntoLineAfterTruncation + " words");
                            createCentrePadding();    
                            applyCentrePadding(lengthLastLine);
                            completeLine = sb.toString();
                        }
                    }  //end of else statement....
                    break;    //breaking out of do while loop
                }//end of while loop
            }//end of try loop
            catch (ArithmeticException e)
            {
                System.out.println("Entering here most likely due to having one word in the line");
                System.out.println("So the StringBuilder should be empty: " + sb.toString());
                sb.append(temp);
                lengthLastLine=lastLine.length();   //length of the last line....
                buffer=k-lengthLastLine;  //buffer is remainder from k.
                System.out.println(lastLine + "   =>qualifies for " + halfExtraPaddingBetweenWords + " padding at front and " + (halfExtraPaddingBetweenWords+totalExtraPaddingBetweenWords) + " at end since it has:" +  wordsIntoLineAfterTruncation + " words");
                createCentrePadding();
                applyCentrePadding(lengthLastLine);
                completeLine = sb.toString();
            }  //end of catch statement...
            completeLinelength = completeLine.length();
            System.out.println("completed line:" + completeLine);
            completedLineRepository[num]=completeLine;
            num++;
            System.out.println("NEW LENGTH of line:" + completeLinelength);
        } //end of if (temp!="")
        
        System.out.println("\n\n****THIS WILL PRINT ENTIRE TEXT**************");
        System.out.println("KEY: "  +  k + " line limit");
        System.out.println(paddingTest + "=Inter-word padding as per requirements");
        System.out.println(existingFrontalPaddingTest + "=existing frontal padding");
        System.out.println("In future, can provision for existing inter-word padding for instance multiple whitespaces..");
        System.out.println("BUT expect user to have single whitespace for the justification to look tidy" + "\n\n");
        
        for (String s: completedLineRepository)
        {
            if (s!=null)
            {
                System.out.println(s);
            }
        }
        System.out.println("*****************************");
        
    }  //end of main method.
}  //end of single class used......