package com.github.lunatrius.imc;

import com.github.lunatrius.core.version.VersionChecker;
import com.github.lunatrius.imc.deserializer.ItemStackDeserializer;
import com.github.lunatrius.imc.deserializer.NBTTagCompoundDeserializer;
import com.github.lunatrius.imc.reference.Reference;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.Mod.Instance;
import cpw.mods.fml.common.ModMetadata;
import cpw.mods.fml.common.event.FMLInterModComms;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Mod(modid = Reference.MODID, name = Reference.NAME, version = Reference.VERSION)
public class DynIMC {
    public static final FilenameFilter IMC_JSON_FILTER = new FilenameFilter() {
        @Override
        public boolean accept(File dir, String name) {
            return name.endsWith(".json");
        }
    };

    @Instance(Reference.MODID)
    public static DynIMC instance;

    private Gson gson;

    @EventHandler
    public void preInit(FMLPreInitializationEvent event) {
        Reference.logger = event.getModLog();
        readConfiguration(event.getModConfigurationDirectory());

        if (Loader.isModLoaded("LunatriusCore")) {
            registerVersionChecker(event.getModMetadata());
        }
    }

    private void readConfiguration(File configurationDirectory) {
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.registerTypeAdapter(ItemStack.class, new ItemStackDeserializer());
        gsonBuilder.registerTypeAdapter(NBTTagCompound.class, new NBTTagCompoundDeserializer());
        this.gson = gsonBuilder.create();

        File cfgDirectory = new File(configurationDirectory, Reference.MODID.toLowerCase());
        if (!cfgDirectory.exists()) {
            if (!cfgDirectory.mkdirs()) {
                Reference.logger.error("Could not create directory!");
            }
        }

        File[] files = cfgDirectory.listFiles(IMC_JSON_FILTER);
        for (File file : files) {
            List<ModIMC> modIMCs = readFile(file);

            if (modIMCs == null) {
                continue;
            }

            Reference.logger.trace("Reading IMC messages from " + file.getName());
            for (ModIMC modIMC : modIMCs) {
                if (modIMC != null) {
                    if (modIMC.stringItemStackMap != null) {
                        for (Map.Entry<String, ItemStack[]> entry : modIMC.stringItemStackMap.entrySet()) {
                            for (ItemStack itemStack : entry.getValue()) {
                                if (itemStack != null && itemStack.getItem() != null) {
                                    Reference.logger.trace("Sending IMC message " + entry.getKey() + ": " + itemStack);
                                    FMLInterModComms.sendRuntimeMessage(Reference.MODID, modIMC.modid, entry.getKey(), itemStack);
                                } else {
                                    Reference.logger.warn("Tried to send null IMC message " + entry.getKey());
                                }
                            }
                        }
                    }

                    if (modIMC.stringStringMap != null) {
                        for (Map.Entry<String, String[]> entry : modIMC.stringStringMap.entrySet()) {
                            for (String string : entry.getValue()) {
                                if (string != null) {
                                    Reference.logger.trace("Sending IMC message " + entry.getKey() + ": " + string);
                                    FMLInterModComms.sendRuntimeMessage(Reference.MODID, modIMC.modid, entry.getKey(), string);
                                } else {
                                    Reference.logger.warn("Tried to send null IMC message " + entry.getKey());
                                }
                            }
                        }
                    }

                    if (modIMC.stringNBTTagCompoundMap != null) {
                        for (Map.Entry<String, NBTTagCompound[]> entry : modIMC.stringNBTTagCompoundMap.entrySet()) {
                            for (NBTTagCompound nbt : entry.getValue()) {
                                if (nbt != null) {
                                    Reference.logger.trace("Sending IMC message " + entry.getKey() + ": " + String.valueOf(nbt));
                                    FMLInterModComms.sendRuntimeMessage(Reference.MODID, modIMC.modid, entry.getKey(), nbt);
                                } else {
                                    Reference.logger.warn("Tried to send a null IMC message " + entry.getKey());
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    private void registerVersionChecker(ModMetadata modMetadata) {
        VersionChecker.registerMod(modMetadata, Reference.FORGE);
    }

    private List<ModIMC> readFile(File file) {
        BufferedReader buffer = null;
        try {
            if (file.getParentFile() != null) {
                if (!file.getParentFile().mkdirs()) {
                    Reference.logger.debug("Could not create directory!");
                }
            }

            if (!file.exists() && !file.createNewFile()) {
                return null;
            }

            if (file.canRead()) {
                FileReader fileInputStream = new FileReader(file);
                buffer = new BufferedReader(fileInputStream);

                String str = "";

                String line;
                while ((line = buffer.readLine()) != null) {
                    str += line + "\n";
                }

                return this.gson.fromJson(str, new TypeToken<ArrayList<ModIMC>>() {}.getType());
            }
        } catch (IOException e) {
            Reference.logger.error("IO failure!", e);
        } catch (JsonSyntaxException e) {
            Reference.logger.error(String.format("Malformed JSON in %s!", file.getName()), e);
        } finally {
            if (buffer != null) {
                try {
                    buffer.close();
                } catch (IOException e) {
                    Reference.logger.error("IO failure!", e);
                }
            }
        }

        return null;
    }
}

@@ -674,16 +674,77 @@
 dComms;%0A
+import cpw.mods.fml.common.event.FMLPostInitializationEvent;%0A
 import c
@@ -1493,16 +1493,44 @@
 on gson;
+%0A    private File directory;
 %0A%0A    @E
@@ -1642,24 +1642,87 @@
 etModLog();%0A
+        this.directory = event.getModConfigurationDirectory();%0A
         read
@@ -1822,24 +1822,24 @@
 usCore%22)) %7B%0A
-
             
@@ -1895,32 +1895,213 @@
        %7D%0A    %7D%0A%0A
+    @EventHandler%0A    public void postInit(FMLPostInitializationEvent event) %7B%0A        if (this.directory != null) %7B%0A            readConfiguration(this.directory);%0A        %7D%0A    %7D%0A%0A
     private void

Move the IMC handing event into postInit.