package org.dynmap.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class ForgeConfigFile {
    private File cfg;
    private HashMap<String, String> settings = new HashMap<String, String>();
    public static final String ALLOWED_CHARS = "._-:";

    public ForgeConfigFile(File cfgfile) {
        cfg = cfgfile;
    }
    
    public boolean load() {
        settings.clear();
        FileInputStream fis = null;
        BufferedReader rdr = null;
        boolean rslt = true;
        
        try {
            fis = new FileInputStream(cfg);
            rdr = new BufferedReader(new InputStreamReader(fis, "UTF-8"));
            String line;
            ArrayList<String> section = new ArrayList<String>();
            String tok = "";
            while((line = rdr.readLine()) != null) {
                boolean skip = false;
                boolean instr = false;
                boolean intok = false;
                tok = "";
                char last_c = ' ';
                for (int i = 0; i < line.length() && !skip; ++i) {
                    char c = line.charAt(i);
                    if(instr) {
                        if(c != '"') {
                            tok += c;
                        }
                        else if (last_c == '"') {
                            // Ignore double double-quotes
                        }
                        else {
                            instr = false;
                            intok = false;
                        }
                    }
                    else if(c == '"') {
                        if (last_c != '"')  {
                            intok = instr = true;
                        }
                    }
                    else if(Character.isLetterOrDigit(line.charAt(i)) || ALLOWED_CHARS.indexOf(line.charAt(i)) != -1) {
                        if(intok) {
                            tok += c;
                        }
                        else {
                            tok = "" + c;
                            intok = true;
                        }
                    }
                    else if (Character.isWhitespace(line.charAt(i))) {
                        if((!instr) && intok) {
                            intok = false;
                        }
                    }
                    else {
                        switch (line.charAt(i)) {
                            case '#':
                                skip = true;
                                instr = intok = false;
                                break;
                            case '{':
                                if(tok.equals("") == false) {
                                    section.add(tok);
                                    tok = "";
                                    instr = intok = false;
                                }
                                break;
                            case '}':
                                if(section.size() > 0) {
                                    section.remove(section.size()-1);
                                }
                                break;
                            case '=':
                            case ':':
                                intok = instr = false;
                                String propertyName = tok;
                                tok = "";
                                int off = propertyName.indexOf(':');
                                if(off >= 0) {  /* Trim off the Forge 6.4.1+ type prefix */
                                    propertyName = propertyName.substring(off+1);
                                }
                                for(int j = section.size()-1; j >= 0; j--) {
                                    propertyName = section.get(j) + "/" + propertyName;
                                }
                                propertyName = propertyName.replace(' ', '_');
                                settings.put(propertyName, line.substring(i + 1).trim());
                                skip = true;
                                break;
                        }
                    }
                    last_c = c;
                }
            }
        } catch (IOException iox) {
            rslt = false;
        } finally {
            if(fis != null) {
                try { fis.close(); } catch (IOException iox) {}
                fis = null;
            }
        }
        return rslt;
    }
    
    public int getBlockID(String id) {
        String val = settings.get(id);
        if (val == null)
            val = settings.get("block/" + id);  /* Check for "block/" */
        if (val != null) {
            val = val.trim();
            if ((val.length() > 0) && Character.isDigit(val.charAt(0))) {
                try {
                    return (int) Double.parseDouble(val);   // Handle floats - used by weird mods like Minegicka for some reason
                } catch (NumberFormatException nfx) {
                }
            }
        }
        return -1;
    }
    public void addBlockIDs(Map<String,Integer> map) {
        for(String k : settings.keySet()) {
            if(k.startsWith("block/")) {
                map.put(k.substring("block/".length()), getBlockID(k));
            }
            else if(k.startsWith("blocks/")) { /* RP2 */
                map.put(k.substring("blocks/".length()), getBlockID(k));
            }
            else if(k.startsWith("item/")) {    /* Item codes? */
                map.put("item_" + k.substring("item/".length()), getBlockID(k));
            }
            else if(k.startsWith("walls/")) {    /* Walls (Fancy Walls) codes? */
                map.put(k, getBlockID(k));
            }
            else if(k.startsWith("world/blocks/")) {    /* XyCraft world/blocks */
                map.put(k.substring("world/".length()), getBlockID(k));
            }
            else {
                map.put(k, getBlockID(k));
            }
        }
    }
}

@@ -243,16 +243,40 @@
 l.Map;%0A%0A
+import org.dynmap.Log;%0A%0A
 public c
@@ -1176,16 +1176,268 @@
  = ' ';%0A
+                int off = line.indexOf(%22: %22);   // If %22tok: value style (Minegicka), fix to look normal%0A                if (off %3E 0) %7B%0A                    line = line.substring(0, off).replace(' ', '_') + %22=%22 + line.substring(off+1);%0A                %7D%0A
         
@@ -2213,30 +2213,17 @@
 OrDigit(
-line.charAt(i)
+c
 ) %7C%7C ALL
@@ -2241,30 +2241,17 @@
 indexOf(
-line.charAt(i)
+c
 ) != -1)
@@ -2568,30 +2568,17 @@
 tespace(
-line.charAt(i)
+c
 )) %7B%0A   
@@ -3579,46 +3579,8 @@
 =':%0A
-                            case ':':%0A
     
@@ -3759,28 +3759,24 @@
             
-int 
 off = proper
@@ -4863,24 +4863,48 @@
 tring id) %7B%0A
+        int idval = -1;%0A
         Stri
@@ -5201,22 +5201,23 @@
         
-return
+idval =
  (int) D
@@ -5422,18 +5422,21 @@
  return 
--1
+idval
 ;%0A    %7D%0A

Fix parsing of funky Minegicka config files