// ALL DONE
// JUST CAN NOT REMEMBER HOW TO FIGURE OUT IF LAST TOKEN....
// SINCE NO TREATMENT HAS TAKEN PLACE ON IT!!!
// THE LOGIC ON APPLICATION WILL FAIL IF ONE WORD
//SINCE IT WILL PROCESS HASMORETOKENS   AND ALSO  !HASMORETOKENS SINCE IT DOESN'T KNOW THE ONLY TOKEN
//TRIGGERS BOTH STATES.....
// I HAVE JUST USED TRY AND CATCH OUT OF THIS AREA OF CODE....
// ALL FIXED NOW!
//I have also avoided any booleans since also more prone to error having to toggle states back to original...
//It now allows end user to customise the padding delimiter.
// This can be useful since it is not possible to count the number of whitespace since it is invisible....

//THE CODE IS DESIGNED TO HAVE THREE WAYS OF OUTPUTTING THE COMPLETED LINE TO END USER:
//1) A line with content truncated
//2) Final line

//TEST CASES (DO NOT UNCOMMENT ANY OF THESE)
//String text = "The quick brown fox jumps over the lazy dog";   (PASSED - this is the example..)
//String text = " This is a test but making it a bit longer!";  (PASSED - spanning more lines..)
//String text = "My";  (PASSED - this is exactly 1 word..)
//String text = "My name is Amit Amlani. This is a sligthly longer test to see if the text can be spanned across multiple lines.";  (PASSED - much longer text)
//String text ="";  (PASSED - no String)
//String text = "This will be 16."  (PASSED - exact length of k)
//String text = "Thiswillbetesting  16 testing."  (PASSED - first word too long exceeds k)
//String text = "  Some blank now            but there should be extreme amount on start second line";  PASSED
//PASSED
//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.";


//With the new code it now functions as below....

/*
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 FullyJustified
{
    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...
        
        // no issues, but it was vital I tried random text from the internet, since I realised
        //my code was not geared towards having 1 word per line...
        //and my test cases had tendency to be biased...
        //now resolved....
        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="";   //last completed line
        int k=50;   // this is the length of the line, the example states 16
        String tokentoString="";  //tokens require conversion to String...
        String line;  // this will be the line before any padding has been applied..
        int wordCount=0;  // a running total of number words.. This will be useful notably when it reaches !hasMoreTokens
        int lineLength; // this is the length of the line before it applies any
        String lineBeforeLastWord="";  //not most friendly name, but it refers to the line with truncation undertaken...
        int lengthLineBeforeLastWord;  // length of the line as described above...
        String completeLine="";  //this will be presented to end user in maximum three possible ways...
        String totalExtraPaddingBetweenWords=""; // This is the padding which needs to be divided equally inter-words..
        int extraPaddingBetweenWords=0;  //this will work in conjunction with totalExtraPaddingBetweenWords to generate the correct amount "  "
        boolean conditionOncePerLine=true; // this is a bit difficult to explain... But since some of my logic was done as part of if else,
        //I wanted to move the code so that it does not repeat.. But it is not possible to put it between the if else
        //since it will be unreachable....
        
        int extraFrontPadding=0;   // total front padding...
        String truncatedWord="";   // this will either contain a single word overspilt or be blank...  
        String delimiter=" ";  // this is used to process any StringTokenizers and get the words...
        int wordsIntoLineAfterTruncation=0;  //  words on line after truncation.. This is very important to understand where padding can be applied..
        int buffer=0; // this is simply   k - (length of line after truncation occured);
        int completeLinelength=0;  // used for onscreen validation to ensure it has reached k
        int lengthLastLine=0;  // length of the last line.....
        int newposText=0;  // will be used as index to navigate through text
        
        String existingFrontalPadding="";  // new code implemented, end user might have existing front padding...
        //Tokenizer strips it off, so has to be manually re-instated....
        String existingFrontalPaddingTest="*";  //End user can select any character, I have differed symbol from 
        // the paddingTest variable...
        
        int existingFrontalPaddingCount=0; // counts amount extra Frontal padding....
        
        String[] completedLineRepository = new String[1000];  // this can be set to preference....
        //not possible to predetermine... but if wanted to extend the code, it can be speculated....
        
        int num=0;  // counter used for completedLineRepository to place all Strings inside.....
        
        //these are two options to test the padding.. Sometimes it is critical especially if padding is on right hand side
        //and to see it visibly....
        //note this includes the natural space between words
        //end user can specify their own padding character
        //note it differs from the full stop.
        //only time the bullet point would become a hindrance if there actually is a bullet point already in the text
        //.Â·    first char is full stop   followed by bullet point....
        String paddingTest = "·";   //used for padding.. same for inter-word and  intra-text
        //String paddingTest = " ";
        
        // I initally wanted to mantain several StringJoiners.
        // During the coding I used 2 or 3... But it could be hazardous if it was not cleared.
        //Also they were used mutually exclusively, so it was an extra risk having different instances..
        
        // So I kept one instance, and it was used:
        StringJoiner sj = new StringJoiner(paddingTest);
        
        int tokenLength=0;  //length of token taken from StringTokenizer
        
        //to avoid mistakes in coding, and setting wrong parameter into the constructor, I have mantained
        //three for readability..
        //First argument is the String text.
        //delimiter is set as " "  since each word has this delimiter...
        StringTokenizer st = new StringTokenizer(text, delimiter);
        String temp="";  // this will hold the value of the token in while loop above to process tokens.
        
        StringTokenizer st1; 
        // constructor will be initial during code as follows:
        //= new StringTokenizer (lineBeforeLastWord, delimiter); 
        String temp1;  // this will hold the value of the token in while loop above to process tokens.
        
        StringTokenizer st2;
        // constructor will be initial during code as follows:
        //=new StringTokenizer(lastLine, delimiter);
        String temp2; // this will hold the value of the token in while loop above to process tokens..
        
        // used so that the string can be manipulated before stored into completed line..
        //on several occasions, it could have been bypassed and StringJoiner store straight into String variable..
        // I prefer the tidiness of StringBuilder..
        StringBuilder sb=new StringBuilder(); 
        
        String alternateToken="";  // was required to distinguish if the front token had existing frontal padding....
       
       //LOGIC
       //need to think about how to allocate spaces...
       //need to keep a count of the words
       
       // *** THIS IS NEW CODE APPEARING STRAIGHT AWAY ***
       //I didn't particularly want to go through the lines in such a manner
       //but it was only way to get existing frontal padding.
       //in principle my whole code could have been completed on this basis, but I wanted
       //to adapt different techniques to enhance my learning experience...
       
       System.out.println("Original Text: " + text +"\n");
       
       //traverse the text
       for (int h=newposText; h<text.length(); h++)
       {
           //if there is a non-whitespace.. this would be consistent with end frontal padding...
           if (text.charAt(h)==' ')
           {
               existingFrontalPadding = existingFrontalPadding + existingFrontalPaddingTest;
               existingFrontalPaddingCount++;  //keeps count of existing frontal paddig...
           }
           
           else
           {
               //setting this h makes it possible in future code to analyse existing padding between words..
               newposText=h;
               //System.out.println("Currently at this position should you wish to implement existing inter-word padding in future: " + h);
               //it has to break to stay inline with start of token..
               break;
           }
       }
       
       
        while (st.hasMoreTokens())  //checking text for tokens....
        {
            //need be careful truncatedWord needs to be added once only, 
            //not each time the hasMoreTokens called...
            //this situation is only valid once it has displayed first word to end user on the screen...
            if (truncatedWord!="")
            {
                sb.append(truncatedWord);  // ommited word from previous line is stored here...
                //this would be the first word back into  the new  line..
                
                //In practice, the following is also valid and saves code:
                //sj.add(truncatedWord) since there are no considerations to format it given its first word..
                sj.add(sb);   //first word added to StringJoiner....
                
                //the content is no longer required, it also prevents re-entering loop until next line is processed..
                //if applicable, i.e when another word is cut off a line due to k
                truncatedWord="";  
                
                sb.delete(0,sb.length());  //the StringBuilder has to be emptied..
                //otherwise this word will form part of consecutive words again...
                
                wordsIntoLineAfterTruncation++;  //total number of words on line increases...
                
            }
            
            
            temp=st.nextToken();   //value of the token stored in temp...
            tokentoString = temp.toString();   //token converted to String...
            tokenLength=tokentoString.length();  //length of token....
            //this is only needed for one sole purpose and ascertain if any word is too long..
            //Unfortunately it can not preemptively get this until token arrives....
            
            //new CODE...
            //applicable if no wordCount...
            //This makes sense since I only increased wordCount once its stored in StringBuilder..
            if (wordCount==0)
            {
                //used for testing.....
                //System.out.println("currently inside String Builder:" + sb.toString());
                
                //this is same as previous code, but this time it adds the padding at front  existingFrontalPadding
                //note existingFrontalPadding can also always be blank, in which case no influence..
                sb.append(existingFrontalPadding);
                sb.append(tokentoString);
                
                //for testing
                //System.out.println("existing frontal padding detected:" + existingFrontalPadding);
                
                //it also has to keep this as the alternate token....
                //since we know that tokenizer will truncate the front white spacing....
                alternateToken= existingFrontalPadding + tokentoString;
                
            }
            
            //it has now increased wordCount....
            wordCount++;  //overall total number of words increases....
            
            //this is still universal and unrelated to first token..
            //since extraFrontPadding would be blank for all except first token...
            //all situations of line getting bigger will be handled in main code...
            
            if ((tokenLength + existingFrontalPaddingCount) >k)
            {
                System.out.println("The following word exceeds line limit of k" + "(" + k + "):" + (temp));
                System.exit(0);  //exit Java code....
            }
            
            //clears StringBuilder since the value is stored in alternate first Token..
            //note again, token will not be alternate for any tokens except the first one...
            sb.delete(0,sb.length());
            
            //***NEW CODE****  Now it is beyond first token...
            if (wordCount>0)
            {
            
            //important for testing...
            //System.out.println("This is the token here:" + tokentoString);
            //System.out.println("This is the alternate token here:" + alternateToken);
            
            
            sb.append(tokentoString);  
            //the StringBuilder will be empty and ready to store a token no different to previous code..
            //but unfortunately this code is repeated twice due to scenarios of pre-storing first word in StringBuffer
            //and afterwards...
            
            //used during testing...
            //System.out.println("677777This is sj.toString():" + sj.toString());    
                
            }
            
            //used for testing.....
            //System.out.println("currently inside StringBuilder again:" + sb.toString());
            
            //always keeps and overwrites this... It is also one word less than what will be sent into 
            //StringJoiner..  Reason is if the k limit is exceeded, it has the line available to roll back to without
            //having to process all tokens again..
            lineBeforeLastWord = sj.toString(); 
            
            //used for testing, once again it is combination of extraFrontPadding + tokentoString
            //System.out.println("ALTERNATE FIRST TOKEN WITH EXISTING FRONTAL PADDING:" + alternateToken);
            
            //used for testing, looking at above code, it will be seen that
            //StringJoiner will have nothing in it, unless a truncatedWord 
            //has been stored in it, so that it can be passed into StringBuilder for new line..
            //It will start process now below, and use right decision making...
            //System.out.println("SJ NOW!!!!: " + sj.toString());
            
            if (existingFrontalPadding=="")
            {
                //this is straight forward since it will use the token that is already added into the
                //StringBuilder
                //note the StringBuilder will only have one word at time since values are passed to
                //StringJoiner for formatting...
                
                //System.out.println("option 1");
            sj.add(sb);  //  StringBuilder added into StringJoiner.... This is a continuous process with delimiter defined...
            
            //System.out.println("This is the token chosen:" + sb.toString());    
                
            }
            
            //as above, there is existingFrontalPadding
            else
            {
                System.out.println("Your existing frontal padding:"+existingFrontalPadding);
                
                //two strings are added to StringJoiner instead....
                //System.out.println("option 2");
                
                //remember alternateToken is tokentoString+extraFrontPadding;
                sj.add(alternateToken);
                
                
                System.out.println("This is the token chosen:" + alternateToken);
            }
            
            //important to clear value now otherwise all tokens will get this padding..
            existingFrontalPadding="";
            
            // ***** FROM HERE ONWARDS, THE LOGIC FLOWS EXACTLY SAME WAY, UNLESS HIGHLIGHTED...
            
            
            sb.delete(0,sb.length());  //remove contents of StringBuffer ready for another token
            
            //used for testing to ensure that it looks like the text...
            //expecting this to grow as .hasMoreTokens continues....
            //System.out.println("INSIDE StringJoiner:" + sj.toString());
            
            
            line = sj.toString();  
            // it also has to keep track of contents in the line.... in order to make decision with k
            
            //used testing....
            //System.out.println("Value of sj.toString: " + line);
            
            //used for testing...
            //System.out.println("unformmated line here so far:" + line);
            
            lineLength=line.length();  //determines length of the line...
            
            //note this value should be exactly same as wordCount if all the words fit naturally and exactly at K boundaries on a line
            //Alternatively, it should also be the same with wordCount on the first line, up to point a word is truncated for exceeding k
            //or it would be the same as wordCount if there is a single line only (irrespective of the number words)
            wordsIntoLineAfterTruncation++;
            
            //System.out.println(extraFrontPadding);
            //Used during testing to ensure that the line was infact getting bigger...
            // it is important to keep this active since it drives all logic..
            System.out.println("Your line getting bigger:" + line + "(" + lineLength + " chars inc white space)");
            System.out.println("Words after truncation: " + wordsIntoLineAfterTruncation);
            
            
            //This is just some pseudo code.....
            //first thing is if the natural line has taken it over k,
            // need to truncate a word.....
            //count length of words...
            // subtract it from k....
            //if less than (wordCount-1)
            //pads at front....    (COMPLETE...)
            
            //completely missed this in my previous coding....
            //it will not store the first line otherwise for such examples (where fullstop is exactly limit of k)
            //String text = "This will be 16. Amit";
            //all housekeeping and reset of variables required as usual once stored in repository.
            //otherwise as a knock on effect !hasMoreTokens will give a negative buffer
            // and padding value will be severely distorted....
                
                //System.out.println("777656456465464value of temp:" + temp);
                
                
                if (lineLength==k)
                {
                   
                    completeLine = line;   //note it is line here not lineBeforeLastWord since no truncation..
                    
                    //stores the line
                    completedLineRepository[num]=line;
                    num++;  //counter for index...
                
                    //System.out.println(completeLine);
                    completeLinelength=completeLine.length();
                    
                    //VERY CRITICAL PART.. ITS FIRST TIME END USER SEES LINE
                    System.out.println("Completed line:" +line);
                
                    //reset StringJoiner inline with a completed line.. This is only time StringJoiner are reset....
                    sj=new StringJoiner(paddingTest);
                 
                    //it is now ready to start counter for a new line....
                    wordsIntoLineAfterTruncation=0;
                 
                    //important to set the padding between words back to none since a new line is being created from scratch.
                    totalExtraPaddingBetweenWords="";
                
                    //it also has to remove contents of StringBuilder, which is always one token in length...
                    sb.delete(0,sb.length());
                
                    //stores completedLine in completedLineRepository to access entire finished lines later....
                
                //Also on this instance, need to remember that temp (the last token) still holds a value
                // on this instance, it has to be erased to entirety..
                //otherwise logic later on will involve truncatedWord=temp..
                //clearly this has not occured..
                
                //this is derived from temp, so best to clear both here....
                tokentoString="";
                temp="";
                
                System.out.println("NEW LENGTH of line:" + completeLinelength);
                
                }
            
            //if the value in lineLength (formed via StringJoiner)  is greater than k
            //k can be adjusted by the end user in above section....
            if (lineLength>k)   
            
            {
                //need remove last token....
                //can not remember how I did that last time..remember
                //kept copy of stringjoiner...
                
                //as explained before, the choice of variable name is a bit poor.
                //but it is the line stored which fits to constraints of k....
                lengthLineBeforeLastWord= lineBeforeLastWord.length();
                
                System.out.println("Rolled back to(due to exceeding " + k +"):" + lineBeforeLastWord);
                System.out.println("Length rolled back line: " + lengthLineBeforeLastWord);
                
                //at this point there clearly is not enough buffer to allow an additional space between 
                //the characters...
                //it has to therefore force the spaces on the left hand side...
                
                //also, if it has rolled back, it needs to store a copy of the last word that was 
                //truncated...
                //otherwise nextToken will bypass it since it is already processed it.
                truncatedWord=temp;
                
                System.out.println("This word getting truncated:" + truncatedWord);
                
                //it now reduces the count since one word has been removed...
                wordsIntoLineAfterTruncation--;
                
                //this is amount excess room on the line..
                buffer = k-lengthLineBeforeLastWord;
                
                //Screen outputs to ensure execution is ok..
                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 there is additional room..
                //if it fills exactly length K the sentence, it does not qualify for padding...
                if (buffer>0)
                {
                    
                    
                // if extra uniform spaces can go between words (such as two between words),
                //this is preferable than adding padding at front... as per requirements....
                //but it is only possible in scenario below....
               
                sj = new StringJoiner(paddingTest);  //resets StringJoiner....
                
                //this will be empty for first line, but needs to be cleared as below thereafter...
                //in practice it would be overwritten, but feels comfortable once content is officially wiped.
                completeLine="";
                
                //note that for every 3 words, inter-word padding is considered at two locations
                // so 1 is subtracted from wordsIntoLineAfterTruncation..
                //it is only possible if there is no remainder from the buffer, so modulus will be taken...
                //the same inter-word spacing has to be adhered to at all times...
                
                //Also need to be careful and consider minimum words in line has to be greater than 1...
                //Otherwise it will start putting inter-word padding which is not possible.
                
                //System.out.println(wordsIntoLineAfterTruncation);
                
                //I had to introduce try as new code....
                // since I never had a situation in my testing that the wordsIntoLineAfterTruncation
                //was 1 on first line... and identical on the next..
                // i.e no space for 2nd word on the 1st line... and no space for 3rd work on 2nd line..
                //it didn't give opportunity for variable to get bigger than 1
                // hence the ArithmeticException
                
                try
                {
                
                if (buffer%(wordsIntoLineAfterTruncation-1)==0 && wordsIntoLineAfterTruncation>1)
                {
                    //uniform extra padding between words...
                    extraPaddingBetweenWords = buffer/(wordsIntoLineAfterTruncation-1);
                
                System.out.println("CURRENT LENGTH of line: " + lengthLineBeforeLastWord);
                
                System.out.println("Qualified for extra padding");
                
                //informs end user...
                System.out.println(extraPaddingBetweenWords + " extra padding between:" + lineBeforeLastWord);
                
                  // This now configures extra padding..
                  // Note this is unrelated to existing space between words....
                  //It will be seen that StringJoiner has two variables in the new instance...
                  //The paddingTest is what end user can specify in variable declaration section at the top...
                  
                   for (int j=0; j<extraPaddingBetweenWords;j++)
                  {
                      totalExtraPaddingBetweenWords = totalExtraPaddingBetweenWords + paddingTest;
                      
                  }
                  
                  // Just good to see if it is goingto plan...
                  //System.out.println("This is the extra padding that will be applied: " + totalExtraPaddingBetweenWords);
                  
                    //the only way to get extra padding between the existing lineBeforeLastWord
                    // is to create another StringTokenizer with same delimiter.
                    // it has to be observed that at this point, that st1 has taken different delimiter...
                    // in st,  it used " " since one expects the initial text to have whitespaces...
                    //but already explained the issue it caused for stripping front padding and reducing inter-word padding to 1.
                    
                    // once st has finished and StringJoiner applied, it is subject to PaddingTest variable for inputting
                    //specified character as delimiter  (in PaddingTest)
                    //so if a bullet point was used, the string that st2 would process would be  ThisÂ·isÂ·a
                    //At this point there would be no more than a single dot between the words 
                    //AND extra frontal padding .. on the end, it is irrelevant... since the text has terminated....
                   
                    System.out.println("It will now process truncated string with extra " + extraPaddingBetweenWords + " padding between the words:" + lineBeforeLastWord);
                    
                    //As described above... different delimiter...
                    st1=new StringTokenizer(lineBeforeLastWord, paddingTest); 
                    
                    // it will now increase delimiter with additional padding...
                    sj = new StringJoiner(paddingTest+totalExtraPaddingBetweenWords); 
                    
                    //getting all tokens..
                    while (st1.hasMoreTokens())
                    {
                        //we know that all tokens will still be constrained by k
                        //the best effort was completed above in creating  lineBeforeLastWord which was as close as possible to k without overrunning..
                        
                        temp1=st1.nextToken();  //storing token....
                        sj.add(temp1);  //adding token to StringJoiner...
                        
                        //Again its useful to see line getting bigger but it will now not overrun k
                        System.out.println("Your line getting bigger:" + sj.toString() + "(" + sj.toString().length() + " chars inc white space)");
                        
                        //adding StringJoiner into the StringBuilder
                        //again, completeLine could be sj.toString()
                        sb.append(sj);
                        
                        // the line is now ready and meets all requirements
                        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);
                 
                } 
                
                // it is entering here since there is uneven buffer to split amongst the words...
                //Note there is buffer>0 since it is still nested within this if loop.....
                //also if there are no tokens, it will process this...
                //the safest way is to ensure that temp!="" and tokentoString!=""
                //This has been set when a string appears with exact k length..
                //but safest way would be checking that truncatedWord is blank since it formed from above...
                //lots options...
                
                else
                {
                    if (temp!="")
                    {
                        
                    extraFrontPadding=buffer; //assigning all spare space at front....
                    System.out.println(lineBeforeLastWord + "   =>qualifies for " + extraFrontPadding + " padding at front since it has:" +  wordsIntoLineAfterTruncation + " words");
                   
                   //preparing the unformatted line for modification.... 
                   sb.append(lineBeforeLastWord);
                
                System.out.println("CURRENT LENGTH of line: " + lengthLineBeforeLastWord);
                
                // now its time to put padding in..... much easier this time...
                for (int b=0; b<buffer; b++)
                {
                    sb.insert(0, paddingTest);  //inserts it at index 0 with the paddingTest 
                    
                }
                
                //the line is now complete...
                completeLine = sb.toString();
                
                //length of line....
                completeLinelength=completeLine.length();
               
                //if this is not equal to k, there has been an error somewhere....
                System.out.println("NEW LENGTH of line after formatting: " + completeLinelength);
                
                // it also needs to keep temp back into StringJoiner since this was last word that was 
                //discarded.
                //note this is not related temp1 even though it has been used recently..
                //temp1 is processing the tokenizer for the line formed in which truncation (lineBeforeLastWord) has occured.
                //Truncation has occured earlier in first StringTokenizer.
                
                sj.add(temp);
                
                }
               
                }
                }  // end of try
                
                //unfortunately it has to repeat the code in above area..... (stuff in else statement)
                //since its dealing with 1 word.......
                //of course if it added a second word... the try would become active....
                //but it is not entirely a repeat...
                //since the requirement is that if its one word per line, the padding is on the right.....
                catch (ArithmeticException e)
                {
                     if (temp!="")
                    {
                        
                    extraFrontPadding=buffer; //assigning all spare space at front....
                    System.out.println(lineBeforeLastWord + "   =>qualifies for " + extraFrontPadding + " padding at end since it has:" +  wordsIntoLineAfterTruncation + " words");
                   
                   //preparing the unformatted line for modification.... 
                   sb.append(lineBeforeLastWord);
                
                System.out.println("CURRENT LENGTH of line: " + lengthLineBeforeLastWord);
                
                // now its time to put padding in..... much easier this time...
                for (int b=0; b<buffer; b++)
                {
                    
                    // lengthLineBeforeLastWord, this is the start index.. since String Builder is zero
                    //index based, lengthLineBeforeLastWord automatically starts one place after existing text....
                    sb.insert((lengthLineBeforeLastWord),paddingTest);  //inserts it at index lengthLineBeforeLastWord with the paddingTest 
                    
                }
                
                //the line is now complete...
                completeLine = sb.toString();
                
                //length of line....
                completeLinelength=completeLine.length();
               
                //if this is not equal to k, there has been an error somewhere....
                System.out.println("NEW LENGTH of line after formatting: " + completeLinelength);
                
                // it also needs to keep temp back into StringJoiner since this was last word that was 
                //discarded.
                //note this is not related temp1 even though it has been used recently..
                //temp1 is processing the tokenizer for the line formed in which truncation (lineBeforeLastWord) has occured.
                //Truncation has occured earlier in first StringTokenizer.
                
                sj.add(temp);
                
                }  //end of if  (temp!="")
                    
                } //end of catch
                
                
                //VERY CRITICAL PART.. ITS FIRST TIME END USER SEES LINE
                System.out.println("Completed line:" +completeLine);
                
                //reset StringJoiner inline with a completed line.. This is only time StringJoiner are reset....
                 sj=new StringJoiner(paddingTest);
                 
                 //it is now ready to start counter for a new line....
                 wordsIntoLineAfterTruncation=0;
                 
                 //important to set the padding between words back to none since a new line is being created from scratch.
                 totalExtraPaddingBetweenWords="";
                
                //it also has to remove contents of StringBuilder, which is always one token in length...
                sb.delete(0,sb.length());
                
                //stores completedLine in completedLineRepository to access entire finished lines later....
                completedLineRepository[num]=completeLine;
                num++;  //counter for index...
                
                //this area of code was useful at this point just to check values in important variables.. 
                //System.out.println("before reset, check values:");
                //System.out.println(sj.toString());
                //System.out.println(lastLine);
                //System.out.println(temp.toString());
                //System.out.println(temp1.toString());
                //System.out.println(temp2.toString());
                //System.out.println(sb.toString();
                
                System.out.println("This word will be carried over to next line:" + temp +"\n");
                
                
                //System.out.println("344What is truncated word count: " + wordsIntoLineAfterTruncation +"(" + line +")  " + line.length() + " chars" );
                
                
                }  //end of if buffer is greater than 0
                
            }  //end of if linelength is greater than k
            
            
        }   //end while (has more tokens)
        
        //for testing....
        //System.out.println("THINGS SHOULD HAVE CLEARED UP!!!!!!!!!!!!!!: " + temp);
        
        
        //String text = "  Some blank now            but there should be extreme amount on start second line";
        
        //CAREFUL........ wasn't sure if needed, so commented incase...
        //wordsIntoLineAfterTruncation=0;
        
        //unfortunately it will repeat several lines of the code as above...
        //I attempted to change structure of the code, but could not find any techniques to consolidate
        // also it is even more impossible since now planning to move into   !hasMoreTokens
        
        // this was a bit challenging, since it required my first usage of try and catch
        // within my programming for over 20 years....
        // I will look to find future uses, if there is a genuine requirement as below....
        
        //considered to be the content not found on any other lines...
        //it can be one word or multiple words....
        lastLine=sj.toString();
        
        System.out.println("Last token processed:" + temp);
        
        System.out.println("******Currently in last line:" + lastLine);
        
        // if there is nothing in the lastline, it has to be assigned what is in temp
        //The logic is a bit difficult to explain here....
        
        // There would be NOTHING in lastline if the StringJoiner was cleared from before.
        //We know StringJoiner is cleared as part of the process of completing lines..
        //So clearly there is NO content remaining to be processed..
        
        //But there is exception, temp is keeping track of the tokens one by one as they arrive.
        //the logic above might have picked up previous token, found that it violated k..
        //So it would have stored this token into truncatedWord
        //We know the truncatedWord is the first item stored in the String Builder
        //And then the StringBuilder is stored inside StringJoiner...
        //So no discrepencies with the truncatedWord being in temp.....
        //In between all this, hasMoreTokens was still running.. and as part of the logic any incoming tokens are stored in temp for a simlar reason...
        //So there is every possibility one word is remaining to be processed..
     
        //the logic is much clearer, and I am leaving my incorrect logic in my previous code..
        //since it is only once I became familiar with my code, I could explain it much better...
        
        
        // ***  THE LOGIC WHICH WAS TECHNICALLY INCORRECT *****  
         // if there is nothing in the lastline, it has to be assigned what is in temp
        //The logic is a bit difficult to explain here....
        
        //There would be nothing in the lastline if ONLY it has undergone no formatting previous lines...
        //In this case, the code would have not reached here in the first place....
        //since it has reached here, the StringJoiners would have cleared....  
        // In which case it would take value temp
        // which is the single truncated word... And the truncated word that will remain in this variable would be 
        //the word cut off the penultimate completed line
        //otherwise, lastline will form sj.toString();
        //So it is picking up the StringJoiner formed right within the first Tokenizer (st)....
        //The question would be as to whether StringJoiner would have have truncated word stored in temp?
        // I am not entirely sure, but I know that having lots System.out.println helped to navigate without issues.
        System.out.println("***************************");
        
        
        if (lastLine=="")
        {
            lastLine=temp;
        }
        
        //Information to end user....
        //need to pay close attention to this and check its not repeated or even blank (in which token was expected)
        // for text such as   "My name is " it is expected to have a lastLine value already
        //for text such as "My "   lastLine is expected to get its value from temp...
        
        //the question that springs to mind is that can more formatted Lines be completed from the left over StringJoiner (stored in lastLine)?
        // logic says no since no more tokens to be received as per !hasMoreTokens();
        //but it still requires a lot of thought... and still not obvious...
        
        System.out.println("Finally completing the last line:" + lastLine);
        
        //used for testing...
        //System.out.println(wordsIntoLineAfterTruncation);
        
        // holds the length last line...
        lengthLastLine = lastLine.length(); 
        
        // I had to force this since there were several calculations involving buffer%0  such as if 1
        //word existed in wordsIntoLineAfterTruncation..
        //we know conditions for padding is wordsIntoLineAfterTruncation-1
        //even checking the condition of buffer%0 will cause issues....
        
        //this means that value has not been cleared as part of having exact k characters on line
        // this is token not processed...
        if (temp!="")
        {
        try
        {
        
        //at this point it has processed all tokens in the text...
        //it is a case of trying to get what is not formatted..
        //
        
        while (!st.hasMoreTokens())
        {
            //need to think here
            
            //thought process
            //wordCount would be identical to wordsIntoLineAfterTruncation if words fitted exactly by k on each line...
            //and with remaining StringJoiner, it becomes irrelevant since no truncation...
            //having a count of this is important throughout 
            
            //this would be expected since value was set to 0 after each completeLine and had no chance to increment.....
            //in the case, there must have been minimum 1 word....
            //wordCount>0 is set as expected.... 
            
            if (wordsIntoLineAfterTruncation==0 && wordCount>0)
            {
                wordsIntoLineAfterTruncation++;
                //even though no truncation performed, it still increments as expected...
            }
            
            
            //The below was also old logic, which was difficult process at time...
            
            //** OLD RATIONALE , NOT EXPLAINED PROPERLY
            //Need to understand how this knows the words in the last line even though it has not processed above...
            //At this point, I quickly realised I did not explore this in my testing....
            //it is expected to force a new line after .  since this is exactly k....
            //String text = "This will be 16. Amit";
            //This failed.. so it raised a concern....
            //at same time, it failed on my old code in exact code region, this was relief
            //so given chance to explore....
            
            // in the left over, it still has entire  text...
            
            //workaround coding... but not used...
            //if (lengthLastLine>tokenLength)
            //{
             //   lastLine=temp;
            //}
            
            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...
           
            // We know content that is remaining will not form any truncation, since
            //it has been handled in all scenarios above....
            
            buffer=k-lengthLastLine;  //seting buffer...
            
            System.out.println("Buffer is: " + buffer);
           
            //PSEUDO CODE
            //a slightly different if condition is required..
            // first part it checks if  buffer can be spread evenly.. And as before, it needs to be longer than
            //1 word long in order for inter-word padding...
            // it can be seen here why the try & catch was required...
            //If there was 1 word in last line, subtracting 1 would give 0...
            //Buffer/0  would give an overflow.......  has to be observed buffer could also be 0...
            // We know however there is a legitimate cause for one word in the line...
            //since it can qualify for padding...
            
            if ((buffer%(wordsIntoLineAfterTruncation-1)==0 && wordsIntoLineAfterTruncation>1) )
                {
                    //same logic as above.....
                    extraPaddingBetweenWords = buffer/(wordsIntoLineAfterTruncation-1);
                    
                    System.out.println("It will now process the string with extra: " + extraPaddingBetweenWords + " padding between words:" + lastLine);
                  
                  //now creating extra padding....
                  if (extraPaddingBetweenWords>0)
                  {
                  for (int j=0; j<extraPaddingBetweenWords;j++)  
                  
                  {
                      totalExtraPaddingBetweenWords = totalExtraPaddingBetweenWords + paddingTest;
                      
                  }
                  }
                  
                  //output to view extra padding....
                  //System.out.println("View extra padding:" + totalExtraPaddingBetweenWords);
                  
                    //the only way to get extra spaces between the existing lastline
                    // is to create another StringTokenizer with same delimiter paddingTest
                    //Then to set up another StringJoiner with new delimiter as below...
                    //same as above for other lines....
                    
                    st2=new StringTokenizer(lastLine, paddingTest);
                    
                    //the overall delimiter has been increased as previously...
                    sj = new StringJoiner(paddingTest + totalExtraPaddingBetweenWords);
                    
                    //used for testing.... although this value has not changed anywhere in the code after
                    //declaration and initialisation....
                    //System.out.println("delimiter should be single white space: " + delimiter);
                    
                    // just used for seeing outputs.... testing....
                    //System.out.println("stringbuilder: " + sb.toString());
                    //System.out.println("current in sj:" + sj.toString());
                    
                    //processing tokens for lastline
                    while (st2.hasMoreTokens())
                    {
                        temp2=st2.nextToken();
                        
                        sj.add(temp2);
                        
                        //Again its useful to see line getting bigger but it will now not overrun k
                        System.out.println("your line getting bigger:" + sj.toString() + "(" + sj.toString().length() + " chars inc white space will NOT exceed " + k + ")");
                        
                    }
                        //The line is now ready.. This is the last line....
                        //It was not so obvious where this message would be provided to end user...
                        //but the fact that it reached here in the try block which still extends downwards,
                        //meant that variable could be accessed...
                        // I knew if the catch executed, this try section of code would become irrelevant similar to if else statement...
                   sb.append(sj); 
                    
                    //delete StringBuffer from 0 to  sb.length()-1
                    sb.delete(0,sb.length());
                    
                    //need to execute code once... can not take it out of if loop since it is proceeded by else
                    //it would break the loop...
                    // this is a part of code which I had no control over, but created flag to execute once per line.
                    if (conditionOncePerLine)
                    {
                    
                    sb.append(sj);
                    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....
              
              //still in the try loop
              
                // it is here because words in the overall word count is greater than 0
                //I complete forgot the if loop initially.
                //in reality it would not matter if the padding is white space.
                //but if it a character in paddingTest, it will flood line with paddingTest
                
                
                //just to understand, this was the if part of the if-else loop
                //it dealt with padding so expected 2 or more wordsIntoLineAfterTruncation...
                //if (buffer%(wordsIntoLineAfterTruncation-1)==0 && wordsIntoLineAfterTruncation>1) 
               
                else
                {
                    if (wordCount>0)
                    {
                    //at this point, temp1 and temp2 are not initialised at all.
                    // it has to be remembered that value of respective temp variables are overwritten within their respective do while loops
                    
                    //temp was associated with the main StringTokenizer for all text...
                    //temp1 was part of the lineBeforeLastWord...   this was all the strings that had formatting...
                    //temp2 was processed just above... again this was part of do while loop, but it has an initialised value...
                    
                    //it has to be one word since the if did not allow entry unless wordsIntoLineAfterTruncation>1
                    //but is it possible to have 0 words in temp?
                    //this is impossible since temp is value from  st.hasMoreTokens  (from original text).
                    //infact none of the temp values can be blank, unless it has not stored the firstToken yet..
                    // or value cleared as in linelength (unformatted) is exactly k
                    
                    //Just to re-iterate, it will not necessarily reach here if there is one word in last line..
                    //since this was the if.... associated with this else...
                    //if ((buffer%(wordsIntoLineAfterTruncation-1)==0 && wordsIntoLineAfterTruncation>1) )
                    //and it can be seen that it would fail at minimum
                    //wordsIntoLineAfterTruncation-1
                    //wordsIntoLineAfterTruncation>1
                    
                    System.out.println("There is one word in last line:" + temp);
                    
                    
                    //I had forgotten to initialise the value of tokentoString and tokenLength in declaration...
                    //this was reason for the below....
                    //This can readily happen, and fortunately it allowed me to reduce old code of initalising them...
                    
                    //**** THIS WAS OLD UNEXPLAINED THOUGHT PROCESS ***********
                    //I also expected the variable tokentoString should also be initialised, but apparently failing..
                    //so having to convert temp back to String...
                    //not sure why value in temp was in scope and not tokentoString which was used in same while loop.
                    //but fortunately situation was recoverable.
                    //also all variables are global throughout the whole code....
                    
                    //No longer required.....
                    //tokentoString =temp.toString();
                    //tokenLength = tokentoString.length();
                    
                    
                    System.out.println("CURRENT LENGTH of line: " + tokenLength);
                    
                    //last line is added and being prepared for formatting....
                    //last line has value of temp in it....
                    sb.append(lastLine);
                
                //information to end user
                System.out.println(lastLine + "   =>qualifies for " + buffer + " padding at end since it has:" +  wordsIntoLineAfterTruncation + " word(s)");
                
                //since it is one word, the requirements are different.
                //all padding is fitted at the end inside the StringBuilder.....
                //only a subtle change required  in the insert....
                
                for (int b=0; b<buffer; b++)
                {
                    //the insertion point would be one position after the last character from initial text was inserted.
                    // due to zero indexing, lengthLastLine is ok....
                    sb.insert((lengthLastLine),paddingTest);
                    
                }
                
                //The complete line is now ready.....
                completeLine = sb.toString();
                
                //No real housekeeping required of variables...
                //since main logical processing is complete unless it enters the catch section...
                //But more importantly, it has to break out of the the do while loop since it will loop infinitely..
                //since it will ALWAYS evaluate !hasMoreTokens
                }
                }  //end of else statement....
          
        break;    //breaking out of do while loop
        }    //end of while loop
    }   //end of try loop
    
    //it has reached here because there was a thrown error such as buffer/0 
    //it has recognised this since wordsIntoLineAfterTruncation-1 = 0   (assuming 1 word was left....)
    //or if there was no buffer in the first place.....
    
    //it has to be questioned how the execution is here if there can be zero words in the line as per the
    //System.out.println()...
    //If blank text is inputted, it skips hasMoreTokens and !hasMoreTokens
    //Theoretically it could have performed System.exit(0);
    //So, running String text=""  does not reach here...
    // I also tried another String text= 
    //it misses the entire try and catch since its in !hasMoreTokens
    // and not subject to any conditions...
    
    
    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());
        
        
        //*** BELOW IS OLD THINKING PROCESS  ********************
        //Again it has to be questioned, why temp is initalised now and not few lines earlier...
        //I relied severely on screen outputs which got me luckily over the line....
        
        //the last token processed in the first StringTokenizer is stored in StringBuilder
        //temp1 and temp2 have not been initialised at this point......
        //but it becomes slightly easier to explain that the StringBuilder is empty....
        
        
        sb.append(temp);
        
        //Again variable Lastline was used when following comment inputted into my code....
        //(NEED EXPAND LATER.....)
        //It is unfortunately becoming difficult to explain, but logic is sustaining for all test scenarios!
        
        lengthLastLine=lastLine.length();   //length of the last line....
        
        buffer=k-lengthLastLine;  //buffer is remainder from k.
        
        //Information to end user....
        System.out.println(lastLine + "   =>qualifies for " + buffer + " padding at end since it has:" +  wordsIntoLineAfterTruncation + " word(s)");
        
                //adding padding at the end.
                for (int b=0; b<buffer; b++)
                {
                    sb.insert((lengthLastLine), paddingTest);
                    
                }
            
                completeLine = sb.toString();
               
               
    }  //end of catch statement...
    
  
    
        completeLinelength = completeLine.length();
        
        //Information to end user.....  
        //Critical part......
        System.out.println("completed line:" + completeLine);
        
        //storing line into repository
        completedLineRepository[num]=completeLine;
        num++;
        System.out.println("NEW LENGTH of line:" + completeLinelength);
        
        }
        
        //This will now print the entire array to the end user....
        System.out.println("\n\n****THIS WILL PRINT ENTIRE TEXT**************");
        //for each loop to print the String values stored in array.........
        
        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......

