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


/*
Online Java - IDE, Code Editor, Compiler

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

// why do we need stringjoiner, stringbuilder        and tokenizer  (split words)  

import java.util.*;

public class Main
{
    public static void main(String[] args) {
        System.out.println("Welcome to Online IDE!! Happy Coding :)");
        
        String text = "The quickbrownfoxjumps over the lazy dog";
        //String text = " This is a test but making it a bit longer!"; 
        //String text = "My";
        
        
        int count=0;
        int k=16;
        String temp="";
        //String sentence;
        String tokentoString;
        String line;
        int wordCount=0;
        int lineLength;
        String lineBeforeLastWord="";
        int lengthLineBeforeLastWord;
        String completeLine;
        String totalExtraPaddingBetweenWords;
        int extraPaddingBetweenWords=0;
        String temp1;
        int lengthfinalToken;
        int extraFrontPadding=0;
        String truncatedWord="";     
        String delimiter=" ";
        int wordIntoLineAfterTruncation=0;
        int buffer=0;
        
        totalExtraPaddingBetweenWords=delimiter;
        
        String sentence="";
        StringJoiner sj = new StringJoiner(delimiter);
        StringJoiner sj1;
        StringJoiner sj2;
        int tokenLength;
        
        StringTokenizer st = new StringTokenizer(text, delimiter);
        StringTokenizer st1;
        StringBuilder sb1 = new StringBuilder();
        StringBuilder sb=new StringBuilder();
       
        while (st.hasMoreTokens())
        {
            //need be careful truncatedWord needs to be added once only, not each time the hasMoreTokens called...
            
            if (truncatedWord!="")
            {
                sb.append(truncatedWord);
                sj.add(sb);
                truncatedWord="";
                sb.delete(0,sb.length());
                wordIntoLineAfterTruncation++;
                
            }
            
            wordCount++;
            
            
            temp=st.nextToken();
            tokentoString = temp.toString();
            tokenLength=tokentoString.length();
            
            System.out.println("aaaa:" + tokenLength);
            if (tokenLength>k)
            {
                System.out.println("The following character exceeds word limit of k" + "(" + k + "):  " + temp);
                System.exit(0);
            }
            
            sb.append(tokentoString);
            
            lineBeforeLastWord = sj.toString();
            
            sj.add(sb);
            sb.delete(0,sb.length());
            line = sj.toString();
            lineLength=line.length();
            
            System.out.println("your sentence getting bigger:" + line);
            
            wordIntoLineAfterTruncation++;
            
            //System.out.println("current length: " + lineLength);
            //System.out.println("number words: " + wordCount);
            
            //need to think about how to allocate spaces...
            //need to keep a count of the words
            
            //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...)
            
            if (lineLength>k)
            {
                //need remove last token....
                //can not remember how I did that last time..remember
                
                //kept copy of stringjoiner...
                
                lengthLineBeforeLastWord= lineBeforeLastWord.length();
                
                System.out.println("rolled back:" + lineBeforeLastWord);
                //System.out.println("Length rolled back line: " + lengthLineBeforeLastWord);
                
                //wordCount;  
                
                //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...
                truncatedWord=temp;
                
                System.out.println("this word getting cut off:" + truncatedWord);
                
                wordIntoLineAfterTruncation--;
                
                //wordIntoLineBeforeTruncation;
                
                buffer = k-lengthLineBeforeLastWord;
                
                //System.out.println("The current buffer is: " + buffer);
                //System.out.println("Number words to accomodate for: " + (wordCount-1));
                
                //The buffer (1) is less than number words (3)
                
                System.out.println("%$£%$£% " + temp);
                System.out.println("What is wordcount here: " + wordCount);
                System.out.println("What is wordcount here: " + wordIntoLineAfterTruncation);
                
                
                //note that for every 3 words, 2 spaces are required....
                if (k-lengthLineBeforeLastWord<wordCount-1)
                {
                    System.out.println("enter");
                
                
                // if extra spaces can go between words (such as two between words),
                //this is preferable than adding padding at front... as per requirements....
                //it is only possible if there is no remainder, so modulus will be taken...
                
                System.out.println("HERE: " + wordIntoLineAfterTruncation);
                System.out.println("Buffer11: " + buffer);
                
                sj2 = new StringJoiner(" ");
             
                if (buffer%(wordIntoLineAfterTruncation-1)==0 && wordIntoLineAfterTruncation!=1)
                {
                    extraPaddingBetweenWords = buffer/(wordIntoLineAfterTruncation-1);
                
                System.out.println("Enter again?");
                
                 System.out.println("HERE1: " + extraPaddingBetweenWords);
                
                        //***************** need to think which loop is this going in.... ****************
                        // it can be nested in one above, but not required....
                        
                  for (int j=0; j<=extraPaddingBetweenWords;j++)
                  {
                      totalExtraPaddingBetweenWords = totalExtraPaddingBetweenWords + " ";
                      System.out.println("terte extra: " + j);
                  }
                  //System.out.println("terte extra: " + j);
                    //the only way to get extra spaces between the existing lineBeforeLastWord
                    // is to create another StringTokenizer with same delimiter " "
                    //Then to set up another StringJoiner with new delimiter as below...
                    // this is bit excessive since could have made the delimiter bigger in st1 instead..
                    //more room for error this way......
                    
                    st1=new StringTokenizer(lineBeforeLastWord, " "); 
                    
                    sj2 = new StringJoiner(totalExtraPaddingBetweenWords);
                    
                    while (st1.hasMoreTokens())
                    {
                        //we know that all tokens will be part of the same line...
                        
                        temp1=st1.nextToken();
                        //sj2.add(temp);   // it has to also add the token that was removed from first string!!
                        sj2.add(temp1);
                        
                    }
                 
                } 
                
                else
                {
                    System.out.println("SHOULD STAY OUT OF HERE!!!!");
                
                //all spaces appended at front to fill the buffer if 1 word in the line....
                
                sb1.append(lineBeforeLastWord);
                
                System.out.println("CURRENT LENGTH----:" + lengthLineBeforeLastWord);
                
                
                //the exercise states pad right hand side of the word
                
                for (int b=0; b<buffer; b++)
                {
                    count++;
                    //since zero index, need to minus 1 from length....
                    sb1.insert((lengthLineBeforeLastWord) ," ");
                    //System.out.println(count + " padding added at front");
                    completeLine = sb1.toString();
                    
                //System.out.println("First line completed:" + completeLine);
                System.out.println("*********************");
                System.out.println(completeLine);
                    
                }
                
                
                //at this point, it needs to wipe out all the contents in the stringjoiner
                // it also needs to keep temp back into it since this was last word that was 
                //discarded.
                sj.add(temp);
               
                }
                System.out.println("Missing");
                System.out.println(sj2.toString());
                
                
                
                //reset all StringJoiners, delete all StringBuilders...
                 sj=new StringJoiner(" ");
                 sj1=new StringJoiner(" ");
                 sj2=new StringJoiner(" ");
                 wordIntoLineAfterTruncation=0;
                totalExtraPaddingBetweenWords="";
                
                //it also has to remove contents of both StringBuilders....
                sb1.delete(0,sb1.length());
                sb.delete(0,sb.length());
                
                }
                
                
                
                
            }
            
            
        }
        
        //unfortunately it will repeat several lines of the code above...
        //but not prepared to change the structure code too much.....
        //so need to check if it fits into k=16
        // and also need to add spaces in front if the word is shorter than k
        
        String lastLine=sj.toString();
        int lengthLastLine = lastLine.length();
        
        try
        {
        while (!st.hasMoreTokens())
        {
            System.out.println("The left over in StringJoiner: " + lastLine);
            System.out.println("words last line: " + wordIntoLineAfterTruncation);
            System.out.println("length: " + lengthLastLine);
            
            buffer=k-lengthLastLine;
            //extraPaddingBetweenWords = buffer%(wordIntoLineAfterTruncation-1);
            //require to minus 1 from word count since padding is divided in between words
            //i.e  3 words,  2 areas for padding....
            
            //System.out.println("padding:" + fa);
            
            System.out.println("Buffer is: " + buffer);
            System.out.println(wordIntoLineAfterTruncation-1);
            
            if (buffer%(wordIntoLineAfterTruncation-1)==0 && wordIntoLineAfterTruncation!=1 || wordIntoLineAfterTruncation!=0)
                {
                    extraPaddingBetweenWords = buffer/(wordIntoLineAfterTruncation-1);
                    
                    System.out.println("extra padding:" + extraPaddingBetweenWords);
                
                System.out.println("Enter again?");
                
                        //***************** need to think which loop is this going in.... ****************
                        // it can be nested in one above, but not required....
                        
                  for (int j=0; j<=extraPaddingBetweenWords;j++)  
                  //note it has to process one extra since the convention is to put a space in between.
                  //hence j<=extraPaddingBetweenWords
                  
                  {
                      totalExtraPaddingBetweenWords = totalExtraPaddingBetweenWords + " ";
                      System.out.println("Value of j: " + j);
                  }
                    //the only way to get extra spaces between the existing lineBeforeLastWord
                    // is to create another StringTokenizer with same delimiter ""
                    //Then to set up another StringJoiner with new delimiter as below...
                    //same as above for other lines....
                    
                    st1=new StringTokenizer(sj.toString(), " ");
                    sj = new StringJoiner(totalExtraPaddingBetweenWords);
                    
                    while (st1.hasMoreTokens())
                    {
                        //we know that all tokens will be part of the same line...
                        
                        temp1=st1.nextToken();
                        sj.add(temp1);   // it has to also add the token that was removed from first string!!
                    }
                 
                } 
        
              
              
                else
                {
                    System.out.println("SHOULD STAY OUT OF HERE!!!!");
                
                //all spaces appended at end to fill the buffer
                
                sb1.append(lastLine);
                
                for (int b=0; b<buffer; b++)
                {
                    count++;
                    sb1.insert(lengthLastLine," ");
                    //System.out.println(count + " padding added at front");
                    
                }
                
                completeLine = sb1.toString();
                //System.out.println("First line completed:" + completeLine);
                System.out.println(completeLine);
                
                //No real housekeeping required of variables...
                //But it has to break out of the the do while loop since it will loop infinitely..
                
                }
          
        break;    
        }
    }
    
    catch (ArithmeticException e)
    {
        System.out.println("Most likely due to having one word in the sentence");
        sb1.append(temp);
        
        lengthLastLine=temp.length();
        buffer=k-lengthLastLine;
                
                for (int b=0; b<buffer; b++)
                {
                    count++;
                    sb1.insert((lengthLastLine)," ");
                    //System.out.println(count + " padding added at front");
                    
                }
                
                completeLine = sb1.toString();
                //System.out.println("First line completed:" + completeLine);
                System.out.println(completeLine);
                System.exit(0);
    }
        
        
        System.out.println(sj);
        
    }
    
}
