/* UtilLib - Copyright (c) 2013-2023 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package net.mapeadores.util.attr;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import net.mapeadores.util.text.CleanedString;
import net.mapeadores.util.text.StringUtils;


/**
 *
 * @author Vincent Calame
 */
public final class AttributeParser {

    private AttributeParser() {
    }

    public static String toString(Attributes attributes) {
        return toString(attributes, "=", ";");
    }

    public static String toString(Attributes attributes, String keySeparator, String separator) {
        StringBuilder buf = new StringBuilder();
        int attributeLength = attributes.size();
        for (int i = 0; i < attributeLength; i++) {
            Attribute attribute = attributes.get(i);
            if (i > 0) {
                buf.append('\n');
            }
            buf.append(attribute.getAttributeKey().toString());
            buf.append(keySeparator);
            int valueLength = attribute.size();
            for (int j = 0; j < valueLength; j++) {
                if (j > 0) {
                    buf.append(separator);
                }
                String value = attribute.get(j);
                int length = value.length();
                for (int k = 0; k < length; k++) {
                    char carac = value.charAt(k);
                    switch (carac) {
                        case '\\':
                        case ';':
                            buf.append('\\');
                    }
                    buf.append(carac);
                }
            }
        }
        return buf.toString();
    }

    public static AttributeChange parse(String text) {
        AttributeChangeBuilder attributeChangeBuilder = new AttributeChangeBuilder();
        parse(attributeChangeBuilder, text);
        return attributeChangeBuilder.toAttributeChange();
    }

    public static void parse(AttributeChangeBuilder attributeChangeBuilder, String text) {
        String[] tokens = StringUtils.getLineTokens(text, StringUtils.EMPTY_EXCLUDE);
        for (String token : tokens) {
            int idx = token.indexOf('=');
            if (idx < 1) {
                continue;
            }
            String key = token.substring(0, idx);
            String values = token.substring(idx + 1);
            try {
                AttributeKey attributeKey = AttributeKey.parse(key);
                List<CleanedString> valueList = parseValues(values);
                if (valueList.isEmpty()) {
                    attributeChangeBuilder.putRemovedAttributeKey(attributeKey);
                } else {
                    attributeChangeBuilder.appendValues(attributeKey, valueList);
                }
            } catch (ParseException pe) {
            }
        }
    }

    public static List<CleanedString> parseValues(String values) {
        List<CleanedString> resultList = new ArrayList<CleanedString>();
        parseValues(resultList, values);
        return resultList;
    }

    public static void parseValues(List<CleanedString> valueList, String values) {
        if (values == null) {
            return;
        }
        int length = values.length();
        if (length == 0) {
            return;
        }
        StringBuilder buf = new StringBuilder();
        boolean ignoreNext = false;
        for (int i = 0; i < length; i++) {
            char carac = values.charAt(i);
            if (ignoreNext) {
                ignoreNext = false;
                buf.append(carac);
            } else {
                if (carac == '\\') {
                    ignoreNext = true;
                } else if (carac == ';') {
                    if (buf.length() > 0) {
                        CleanedString cs = CleanedString.newInstance(buf.toString());
                        if (cs != null) {
                            valueList.add(cs);
                        }
                        buf = new StringBuilder();
                    }
                } else {
                    buf.append(carac);
                }
            }
        }
        if (buf.length() > 0) {
            CleanedString cs = CleanedString.newInstance(buf.toString());
            if (cs != null) {
                valueList.add(cs);
            }
        }
    }

}
