package com.github.richardjwild.randomizer.types.pattern.parserstate;

import com.github.richardjwild.randomizer.types.pattern.StringPatternBuilder;
import com.github.richardjwild.randomizer.types.pattern.StringPatternParser;
import com.github.richardjwild.randomizer.types.pattern.StringPatternParserException;

import java.util.List;

import static com.github.richardjwild.randomizer.localization.Messages.*;
import static java.lang.Integer.parseInt;

public class DefineRangeLengthState extends ParserState {

    private final List<Character> permittedCharacters;
    private final StringBuilder lengthBuilder = new StringBuilder();

    public DefineRangeLengthState(StringPatternParser parser, StringPatternBuilder builder, List<Character> permittedCharacters) {
        super(parser, builder);
        this.permittedCharacters = permittedCharacters;
    }

    @Override
    public ParserState handleCharacter(char c) {
        if (c == '}') {
            setElementLength(lengthBuilder.toString());
            return new DefineLiteralPatternState(parser, builder);
        } else {
            lengthBuilder.append(c);
            return this;
        }
    }

    @Override
    public void patternEnded() {
        if (lengthBuilder.length() == 0)
            throw new StringPatternParserException(UNEXPECTED_PATTERN_END_WANTED_NUMBER);
        throw new StringPatternParserException(UNEXPECTED_PATTERN_END_WANTED_NUMBER_COMMA_CLOSECURLYBRACE);
    }

    private void setElementLength(String elementLengthDefinition) {
        String[] parts = elementLengthDefinition.split(",");
        switch (parts.length) {
            case 1:
                if (elementLengthDefinition.endsWith(","))
                    throw new StringPatternParserException(MISSING_VALUE_IN_LENGTH_DEFINITION);
                builder.addFixedLengthElement(readInt(parts[0]), permittedCharacters);
                break;
            case 2:
                builder.addRandomLengthElement(readInt(parts[0]), readInt(parts[1]), permittedCharacters);
                break;
            default:
                throw new StringPatternParserException(TOO_MANY_FIELDS_IN_LENGTH_DEFINITION,
                        Integer.valueOf(parts.length).toString());
        }
    }

    private int readInt(String s) {
        if (s.isEmpty())
            throw new StringPatternParserException(MISSING_VALUE_IN_LENGTH_DEFINITION);
        return tryParseInt(s);
    }

    private int tryParseInt(String s) {
        try {
            return parseInt(s);
        } catch (NumberFormatException e) {
            throw new StringPatternParserException(INVALID_NUMBER_IN_LENGTH_DEFINITION);
        }
    }
}

@@ -445,16 +445,55 @@
 arseInt;
+%0Aimport static java.lang.String.format;
 %0A%0Apublic
@@ -638,23 +638,26 @@
 r length
-Builder
+Definition
  = new S
@@ -707,16 +707,29 @@
 thState(
+%0A            
 StringPa
@@ -747,16 +747,28 @@
  parser,
+%0A           
  StringP
@@ -789,16 +789,28 @@
 builder,
+%0A           
  List%3CCh
@@ -838,16 +838,20 @@
 racters)
+%0A   
  %7B%0A     
@@ -1043,38 +1043,48 @@
     
-set
+addStringPattern
 Element
-L
+(l
 ength
-(lengthBuilder
+Definition
 .toS
@@ -1195,23 +1195,26 @@
   length
-Builder
+Definition
 .append(
@@ -1324,23 +1324,26 @@
  (length
-Builder
+Definition
 .length(
@@ -1576,32 +1576,39 @@
 oid 
-set
+addStringPattern
 Element
-Length
 (String 
 elem
@@ -1603,25 +1603,18 @@
 (String 
-e
 le
-mentLe
 ngthDefi
@@ -1648,24 +1648,17 @@
 parts = 
-elementL
+l
 engthDef
@@ -1689,14 +1689,10 @@
     
-switch
+if
  (pa
@@ -1701,16 +1701,21 @@
 s.length
+ == 1
 ) %7B%0A    
@@ -1726,44 +1726,13 @@
     
-case 1:%0A                if (elementL
+if (l
 engt
@@ -1758,20 +1758,16 @@
 h(%22,%22))%0A
-    
         
@@ -1850,24 +1850,64 @@
 ITION);%0A    
+        int length = readInt(parts%5B0%5D);%0A
             
@@ -1936,33 +1936,22 @@
 Element(
-readInt(parts%5B0%5D)
+length
 , permit
@@ -1978,42 +1978,133 @@
     
-        break;%0A            case 2:
+%7D else if (parts.length == 2) %7B%0A            int minLength = readInt(parts%5B0%5D);%0A            int maxLength = readInt(parts%5B1%5D);
 %0A   
@@ -2104,36 +2104,32 @@
 %5D);%0A            
-    
 builder.addRando
@@ -2147,116 +2147,69 @@
 ent(
-readInt(parts%5B0%5D), readInt(parts%5B1%5D), permittedCharacters);%0A                break;%0A            default:%0A    
+minLength, maxLength, permittedCharacters);%0A        %7D else %7B%0A
     
@@ -2255,16 +2255,37 @@
 ception(
+%0A                    
 TOO_MANY
@@ -2338,28 +2338,21 @@
     
-    Integer.valueOf(
+format(%22%25d%22, 
 part
@@ -2360,27 +2360,16 @@
 .length)
-.toString()
 );%0A     
@@ -2521,32 +2521,49 @@
 TH_DEFINITION);%0A
+        else%0A    
         return t

Refactor DefineRangeLengthState for greater clarity