package sed;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.jdom.Element;

import sed.weather.PropertySet;

import com.jme3.asset.AssetKey;
import com.jme3.asset.AssetManager;
import com.jme3.math.Vector3f;

/**
 * Builder for a {@link PropertySet} that accept it's specification via
 * {@link XMLPropertySetBuilder#putFloat(String)} etc and reads the concrete values
 * from (optionally multiple) asset XML file(s) given by file name.
 * 
 * @author cn
 */
public class XMLPropertySetBuilder {
    
    // TODO: how to test jME dependent classes?
    
    private static final Pattern patVec3 = Pattern.compile("^\\((.+),(.+),(.+)\\)$");
    private static final Pattern patIntArray = Pattern.compile("^\\[(.*)\\]$");
    
    private Element[] weatherXml;
    private PropertySet[] result;
    
    public XMLPropertySetBuilder(AssetManager mgr, String... names) {
        weatherXml = new Element[names.length];
        result = new PropertySet[names.length];
        for(int i = 0; i < names.length; i++) {
            weatherXml[i] = mgr.loadAsset(new AssetKey<Element>(String.format("weather/%s.xml", names[i])));
            result[i] = new PropertySet(names[i]);
        }
    }
    
    public void putFloat(String key) {
        for(int i = 0; i < weatherXml.length; i++) {
            String data = getXMLText(i, key).trim();
            try {
                result[i].put(key, (Float) Float.valueOf(data), Float.class);
            } catch(NumberFormatException ex) {
                throw new ParseException(String.format("Property %s: parsing failed", key), ex); 
            }
        }
    }
    
    public void putVec3(String key) {
        for(int i = 0; i < weatherXml.length; i++) {
            String data = getXMLText(i, key).trim();
            Matcher m = patVec3.matcher(data);
            if(m.matches()) {
                result[i].put(key, new Vector3f(
                    Float.parseFloat(m.group(1).trim()),
                    Float.parseFloat(m.group(2).trim()),
                    Float.parseFloat(m.group(3).trim())), Vector3f.class);
            } else {
                throw new ParseException("Not a Vector3f: "+data);
            }
        }
    }
    
    public void putInt(String key) {
        for(int i = 0; i < weatherXml.length; i++) {
            String data = getXMLText(i, key).trim();
            try {
                result[i].put(key, (Integer) Integer.valueOf(data, 10), Integer.class);
            } catch(NumberFormatException ex) {
                throw new ParseException(String.format("Property %s: parsing failed", key), ex); 
            }
        }
    }
    
    public void putIntArray(String key) {
        for(int i = 0; i < weatherXml.length; i++) {
            String data = getXMLText(i, key).trim();
            Matcher m = patIntArray.matcher(data);
            if(m.matches()) {
                String[] array = m.group(1).split(",");
                Integer[] intArray = new Integer[array.length];
                for(int j = 0; j < array.length; j++) {
                    intArray[j] = Integer.parseInt(array[j].trim(), 10);
                }
                result[i].put(key, intArray, Integer[].class);
            } else {
                throw new NumberFormatException("Not an Integer[]: "+data);
            }
        }
    }
    
    public void putBool(String key) {
        for(int i = 0; i < weatherXml.length; i++) {
            String data = getXMLText(i, key).trim();
            try {
                result[i].put(key, (Boolean) Boolean.valueOf(data), Boolean.class);
            } catch(NumberFormatException ex) {
                throw new ParseException(String.format("Property %s: parsing failed", key), ex); 
            }
        }
    }
    
    public PropertySet getResult() {
        return result.length == 0 ? result[0] : null;
    }
    
    public PropertySet getResult(int idx) {
        return result[idx];
    }
    
    public PropertySet[] getResults() {
        return result;
    }
    
    private String getXMLText(int idx, String key) {
        Element cur = weatherXml[idx];
        String[] parts = key.split("\\.");
        for(int i = 0; i < parts.length; i++) {
//            System.out.println(childreen[i]);
            cur = cur.getChild(parts[i]);
            if(cur == null) {
                throw new ParseException(String.format("Property %s: no XML data not found!", key));
            }
        }
        return cur.getText();
    }
    
    public static class ParseException extends RuntimeException {

        public ParseException() {
            super();
        }

        public ParseException(String message, Throwable cause) {
            super(message, cause);
        }

        public ParseException(String message) {
            super(message);
        }

        public ParseException(Throwable cause) {
            super(cause);
        }
    }
}

@@ -3839,16 +3839,23 @@
 h == 0 ?
+ null :
  result%5B
@@ -3860,15 +3860,8 @@
 t%5B0%5D
- : null
 ;%0A  

Fix bug producing NullPointerException