package estivate.converter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import estivate.core.Converter;
import lombok.extern.slf4j.Slf4j;

/**
 * Format sample: "picto-(\\w)?\\.png"
 * 
 * @author Benoit Theunissen
 *
 */
@Slf4j
public class RegexExtractorConvertor implements Converter {

    public static final Map<String, Pattern> PATTERNS = new HashMap<String, Pattern>();

    public boolean canConvert(Object value, Class<?> targetType) {
        return targetType.isAssignableFrom(int.class) || targetType.isAssignableFrom(int[].class)
                || targetType.isAssignableFrom(String.class) || targetType.isAssignableFrom(String[].class);
    }

    public Object convert(Object value, Class<?> targetType, String format) {

        Pattern compile = getPattern(format);
        Matcher matcher = compile.matcher(value.toString());

        List<String> matches = new ArrayList<String>();

        while (matcher.find()) {
            int groupCount = matcher.groupCount();
            for (int i = 0; i < groupCount; i++) {
                String current = matcher.group(i + 1);
                log.debug("matching: {}", current);
                matches.add(current);
            }
        }
        if (matches.isEmpty()) {
            throw new RuntimeException("Expression '" + format + "' cant match '" + value.toString() + "'");
        }

        if (targetType.isAssignableFrom(int.class)) {
            return Integer.parseInt(matches.get(0));
        }
        if (targetType.isAssignableFrom(int[].class)) {

            int[] result = new int[matches.size()];
            int idx = 0;
            for (String match : matches) {
                result[idx++] = Integer.parseInt(match);
            }

            return result;
        }
        if (targetType.isAssignableFrom(String[].class)) {
            return matches.toArray(new String[] {});
        }

        return matches.get(0);
    }

    private Pattern getPattern(String format) {
        Pattern pattern = PATTERNS.get(format);
        if (pattern == null) {
            pattern = Pattern.compile(format);
            PATTERNS.put(format, pattern);
        }
        return pattern;
    }

}

@@ -683,16 +683,123 @@
 class)%0D%0A
+                %7C%7C targetType.isAssignableFrom(short.class) %7C%7C targetType.isAssignableFrom(short%5B%5D.class)%0D%0A
         
@@ -1741,32 +1741,154 @@
 ));%0D%0A        %7D%0D%0A
+        if (targetType.isAssignableFrom(short.class)) %7B%0D%0A            return Short.parseShort(matches.get(0));%0D%0A        %7D%0D%0A
         if (targ
@@ -2120,32 +2120,334 @@
            %7D%0D%0A%0D%0A
+            return result;%0D%0A        %7D%0D%0A        if (targetType.isAssignableFrom(short%5B%5D.class)) %7B%0D%0A%0D%0A            short%5B%5D result = new short%5Bmatches.size()%5D;%0D%0A            int idx = 0;%0D%0A            for (String match : matches) %7B%0D%0A                result%5Bidx++%5D = Short.parseShort(match);%0D%0A            %7D%0D%0A%0D%0A
             retu

handle 'short' type