/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.text.format;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.ranides.assira.math.Bitwise;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public final class AnsiStrings {
    
    private AnsiStrings() {
        // utility class
    }
    
    private static final Pattern VALUE_OF_RE = Pattern.compile(
        "(?:AnsiAttr\\{)?([0-9]+)\\s+([0-9]+)(?:\\s+([0-9]+))?(?:\\s+([a-z\\+\\- ]+)|\\s+([0-9]+))?\\}?"
    );

    private static final int VALUE_OF_INT[] = {
        AnsiAttr.BOLD,
        AnsiAttr.UNDERLINE,
        AnsiAttr.INVERT,
        AnsiAttr.SYMBOL,
        AnsiAttr.NARROW,
        AnsiAttr.STRIKE,
        AnsiAttr.FRESH,
        AnsiAttr.CHANGED,
        
        AnsiAttr.NO_BOLD,
        AnsiAttr.NO_UNDERLINE,
        AnsiAttr.NO_INVERT,
        AnsiAttr.NO_SYMBOL,
        AnsiAttr.NO_NARROW,
        AnsiAttr.NO_STRIKE,
        AnsiAttr.NO_FRESH,
        AnsiAttr.NO_CHANGED,
        
        AnsiAttr.MASK_FLAGS_CLR
    };
    
    private static final String VALUE_OF_STR[] = {
        "+b",
        "+u",
        "+i",
        "+m",
        "+n",
        "+s",
        "+f",
        
        "+c",
        "-b",
        "-u",
        "-i",
        "-m",
        "-n",
        "-s",
        "-f",
        "-c",
        
        "r"
    };
    
    public static AnsiAttr attr(int back, int fore) {
        return AnsiStrings.attr(back, fore, 0);
    }
    
    public static AnsiAttr attr(int back, int fore, int font) {
        return AnsiStrings.attr(back, fore, font, AnsiAttr.NORMAL | AnsiAttr.MASK_FLAGS_CLR);
    }
    
    public static AnsiAttr attr(int back, int fore, int font, int flags) {
        return new AnsiAttr.Value(back, fore, font, flags);
    }
    
    public static AnsiAttr attr(int back, int fore, int font, String flags) {
        return new AnsiAttr.Value(back, fore, font, decodeFlags(flags));
    }
    
    public static AnsiAttr attr(String pattern) {
        Matcher hit = VALUE_OF_RE.matcher(pattern);
        if(!hit.matches()) {
            throw new IllegalArgumentException(pattern);
        }
        int back = Integer.parseInt(hit.group(1));
        int fore = Integer.parseInt(hit.group(2));
        int font = 0;
        if(null != hit.group(3)) {
            font = Integer.parseInt(hit.group(3));
        }
        return new AnsiAttr.Value(back, fore, font, decodeFlags(hit.group(4)));
    }
    
    public static void apply(AnsiCharSequence text, AnsiAttr attr) {
        text.setAttr(0, text.length(), attr);
    }
    
    public static int decodeFlags(String value) {
        if(null == value) {
            return AnsiAttr.NORMAL;
        }
        int ret = 0;
        for(int i=0, n=VALUE_OF_INT.length; i<n; i++) {
            if( value.contains(VALUE_OF_STR[i]) ) {
                ret |= VALUE_OF_INT[i];
            }
        }
        return ret;
    }
    
    public static String encodeFlags(int value) {
        StringBuilder ret = new StringBuilder();
        for(int i=0, n=VALUE_OF_INT.length; i<n; i++) {
            if( Bitwise.has(value, VALUE_OF_INT[i]) ) {
                ret.append(VALUE_OF_STR[i]);
            }
        }
        return ret.toString();
    }
    
    
    
}
