/*
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 LeftJustified
{
    public static void main(String[] args) {
        System.out.println("Welcome to Online IDE!! Happy Coding :)");
        
        //THESE ARE ALL TEST CASES......SELECT ONE ONLY!
        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="";
        int k=16;
        String tokentoString="";
        String line;
        int wordCount=0;
        int lineLength;
        String lineBeforeLastWord="";
        int lengthLineBeforeLastWord;
        String completeLine="";
        String totalExtraPaddingBetweenWords="";
        int extraPaddingBetweenWords=0;
        boolean conditionOncePerLine=true;
        int extraFrontPadding=0;
        String truncatedWord="";
        String delimiter=" ";
        int wordsIntoLineAfterTruncation=0;
        int buffer=0;
        int completeLinelength=0;
        int lengthLastLine=0;
        int newposText=0;
        String existingFrontalPadding="";
        String existingFrontalPaddingTest="*";
        int existingFrontalPaddingCount=0;
        String[] completedLineRepository = new String[1000];
        int num=0;
        String paddingTest = "Â·";
        StringJoiner sj = new StringJoiner(paddingTest);
        int tokenLength=0;
        StringTokenizer st = new StringTokenizer(text, delimiter);
        String temp="";
        StringTokenizer st1;
        String temp1;
        StringTokenizer st2;
        String temp2;
        StringBuilder sb=new StringBuilder();
        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;
                totalExtraPaddingBetweenWords="";
                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)
                        {
                            extraPaddingBetweenWords = buffer;
                            System.out.println("CURRENT LENGTH of line: " + lengthLineBeforeLastWord);
                            System.out.println("Qualified for extra padding");
                            System.out.println(extraPaddingBetweenWords + " extra padding in front of:" + lineBeforeLastWord);
                
                            for (int j=0; j<extraPaddingBetweenWords;j++)
                            {
                                totalExtraPaddingBetweenWords = totalExtraPaddingBetweenWords + paddingTest;
                            }
                            System.out.println("It will now process truncated string with extra " + extraPaddingBetweenWords + " padding between the words:" + lineBeforeLastWord);
                            st1=new StringTokenizer(lineBeforeLastWord, paddingTest); 
                    
                            while (st1.hasMoreTokens())
                            {
                                temp1=st1.nextToken();
                                sj.add(temp1);
                                System.out.println("Your line getting bigger:" + sj.toString() + "(" + sj.toString().length() + " chars inc white space)");
                                sb.append(sj);
                                sb.insert(sj.length(),totalExtraPaddingBetweenWords);
                                completeLine=sb.toString();
                                sb.delete(0,sb.length()); //removes content from index 0 to sb.length()-1
                            }
                            System.out.println("NEW LENGTH of line after formatting: " + completeLinelength);
                        }
                        else
                        {
                            if (temp!="")
                            {
                                extraFrontPadding=buffer;
                                System.out.println(lineBeforeLastWord + "   =>qualifies for " + extraFrontPadding + " padding at front since it has:" +  wordsIntoLineAfterTruncation + " words");
                 
                                sb.append(lineBeforeLastWord);
                                System.out.println("CURRENT LENGTH of line: " + lengthLineBeforeLastWord);
                
                                for (int b=0; b<buffer; b++)
                                {
                                    sb.insert(lengthLineBeforeLastWord, paddingTest);  //inserts it at end of StringBuilder 
                                }
                                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!="")
                        {
                            extraFrontPadding=buffer;
                            System.out.println(lineBeforeLastWord + "   =>qualifies for " + extraFrontPadding + " padding at front since it has:" +  wordsIntoLineAfterTruncation + " words");
                            sb.append(lineBeforeLastWord);
                            System.out.println("CURRENT LENGTH of line: " + lengthLineBeforeLastWord);
                
                            for (int b=0; b<buffer; b++)
                            {
                                sb.insert(lengthLineBeforeLastWord,paddingTest);
                            }
                            
                            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;
                    totalExtraPaddingBetweenWords="";
                    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); // more simple to follow...
           
                    buffer=k-lengthLastLine;
                    System.out.println("Buffer is: " + buffer);
                    
                    if ((buffer%(wordsIntoLineAfterTruncation-1)==0 && wordsIntoLineAfterTruncation>1) )
                    {
                        extraPaddingBetweenWords = buffer;
                        System.out.println("It will now process the string with extra: " + extraPaddingBetweenWords + " in front of:" + lastLine);
                        
                        if (extraPaddingBetweenWords>0)
                        {
                            for (int j=0; j<extraPaddingBetweenWords;j++)  
                            {
                                totalExtraPaddingBetweenWords = totalExtraPaddingBetweenWords + paddingTest;
                            }
                        }
                        
                        st2=new StringTokenizer(lastLine, paddingTest);
                        sj = new StringJoiner(paddingTest);
                        
                        while (st2.hasMoreTokens())
                        {
                            temp2=st2.nextToken();
                            sj.add(temp2);
                            System.out.println("your line getting bigger:" + sj.toString() + "(" + sj.toString().length() + " chars inc white space will NOT exceed " + k + ")");
                        }
                        
                        if (conditionOncePerLine)
                        {
                            sb.append(sj);
                            sb.insert(sj.length(),totalExtraPaddingBetweenWords);
                            completeLine=sb.toString();
                            conditionOncePerLine=false;
                        }
                    } //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 " + buffer + " padding at front since it has:" +  wordsIntoLineAfterTruncation + " word(s)");
                
                            for (int b=0; b<buffer; b++)
                            {
                                sb.insert(lengthLastLine,paddingTest);
                            }
                            
                            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();
                buffer=k-lengthLastLine;
                System.out.println(lastLine + "   =>qualifies for " + buffer + " padding at front since it has:" +  wordsIntoLineAfterTruncation + " word(s)");
                
                for (int b=0; b<buffer; b++)
                {
                    sb.insert(lengthLastLine, paddingTest);
                }
                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......