001package net.minecraftforge.common;
002
003import java.io.BufferedWriter;
004import java.io.IOException;
005import java.util.ArrayList;
006import java.util.Collection;
007import java.util.Map;
008import java.util.Set;
009import java.util.TreeMap;
010
011import com.google.common.base.Splitter;
012
013import static net.minecraftforge.common.Configuration.*;
014
015public class ConfigCategory implements Map<String, Property>
016{
017    private String name;
018    private String comment;
019    private ArrayList<ConfigCategory> children = new ArrayList<ConfigCategory>();
020    private Map<String, Property> properties = new TreeMap<String, Property>();
021    public final ConfigCategory parent;
022
023    public ConfigCategory(String name)
024    {
025        this(name, null);
026    }
027
028    public ConfigCategory(String name, ConfigCategory parent)
029    {
030        this.name = name;
031        this.parent = parent;
032        if (parent != null)
033        {
034            parent.children.add(this);
035        }
036    }
037
038    public boolean equals(Object obj)
039    {
040        if (obj instanceof ConfigCategory)
041        {
042            ConfigCategory cat = (ConfigCategory)obj;
043            return name.equals(cat.name) && children.equals(cat.children);  
044        }
045        
046        return false;
047    }
048
049    public String getQualifiedName()
050    {
051        return getQualifiedName(name, parent);
052    }
053
054    public static String getQualifiedName(String name, ConfigCategory parent)
055    {
056        return (parent == null ? name : parent.getQualifiedName() + Configuration.CATEGORY_SPLITTER + name);
057    }
058
059    public ConfigCategory getFirstParent()
060    {
061        return (parent == null ? this : parent.getFirstParent());
062    }
063
064    public boolean isChild()
065    {
066        return parent != null;
067    }
068
069    public Map<String, Property> getValues()
070    {
071        return properties;
072    }
073
074    public void setComment(String comment)
075    {
076        this.comment = comment;
077    }
078
079    public boolean containsKey(String key)
080    {
081        return properties.containsKey(key);
082    }
083
084    public Property get(String key)
085    {
086        return properties.get(key);
087    }
088
089    public void set(String key, Property value)
090    {
091        properties.put(key, value);
092    }
093
094    public void write(BufferedWriter out, int indent) throws IOException
095    {
096        String pad = getIndent(indent);
097
098        out.write(pad + "####################" + NEW_LINE);
099        out.write(pad + "# " + name + NEW_LINE);
100
101        if (comment != null)
102        {
103            out.write(pad + "#===================" + NEW_LINE);
104            Splitter splitter = Splitter.onPattern("\r?\n");
105
106            for (String line : splitter.split(comment))
107            {
108                out.write(pad + "# " + line + NEW_LINE);
109            }
110        }
111
112        out.write(pad + "####################" + NEW_LINE + NEW_LINE);
113
114        if (!allowedProperties.matchesAllOf(name))
115        {
116            name = '"' + name + '"';
117        }
118
119        out.write(pad + name + " {" + NEW_LINE);
120
121        pad = getIndent(indent + 1);
122
123        Property[] props = properties.values().toArray(new Property[properties.size()]);
124
125        for (int x = 0; x < props.length; x++)
126        {
127            Property prop = props[x];
128
129            if (prop.comment != null)
130            {
131                if (x != 0)
132                {
133                    out.newLine();
134                }
135
136                Splitter splitter = Splitter.onPattern("\r?\n");
137                for (String commentLine : splitter.split(prop.comment))
138                {
139                    out.write(pad + "# " + commentLine + NEW_LINE);
140                }
141            }
142
143            String propName = prop.getName();
144
145            if (!allowedProperties.matchesAllOf(propName))
146            {
147                propName = '"' + propName + '"';
148            }
149
150            if (prop.isList())
151            {
152                out.write(String.format(pad + "%s:%s <" + NEW_LINE, prop.getType().getID(), propName));
153                pad = getIndent(indent + 2);
154
155                for (String line : prop.valueList)
156                {
157                    out.write(pad + line + NEW_LINE);
158                }
159
160                out.write(getIndent(indent + 1) + " >" + NEW_LINE);
161            }
162            else if (prop.getType() == null)
163            {
164                out.write(String.format(pad + "%s=%s" + NEW_LINE, propName, prop.value));
165            }
166            else
167            {
168                out.write(String.format(pad + "%s:%s=%s" + NEW_LINE, prop.getType().getID(), propName, prop.value));
169            }
170        }
171
172        for (ConfigCategory child : children)
173        {
174            child.write(out, indent + 1);
175        }
176
177        out.write(getIndent(indent) + "}" + NEW_LINE + NEW_LINE);
178    }
179
180    private String getIndent(int indent)
181    {
182        StringBuilder buf = new StringBuilder("");
183        for (int x = 0; x < indent; x++)
184        {
185            buf.append("    ");
186        }
187        return buf.toString();
188    }
189
190
191    //Map bouncer functions for compatibility with older mods, to be removed once all mods stop using it.
192    @Override public int size(){ return properties.size(); }
193    @Override public boolean isEmpty() { return properties.isEmpty(); }
194    @Override public boolean containsKey(Object key) { return properties.containsKey(key); }
195    @Override public boolean containsValue(Object value){ return properties.containsValue(value); }
196    @Override public Property get(Object key) { return properties.get(key); }
197    @Override public Property put(String key, Property value) { return properties.put(key, value); }
198    @Override public Property remove(Object key) { return properties.remove(key); }
199    @Override public void putAll(Map<? extends String, ? extends Property> m) { properties.putAll(m); }
200    @Override public void clear() { properties.clear(); }
201    @Override public Set<String> keySet() { return properties.keySet(); }
202    @Override public Collection<Property> values() { return properties.values(); }
203    @Override public Set<java.util.Map.Entry<String, Property>> entrySet() { return properties.entrySet(); }
204
205}