package com.cookpad.puree;

import com.google.gson.Gson;
import com.google.gson.JsonObject;

import com.cookpad.puree.internal.LogDumper;
import com.cookpad.puree.outputs.PureeOutput;
import com.cookpad.puree.storage.PureeDbHelper;
import com.cookpad.puree.storage.PureeStorage;
import com.cookpad.puree.storage.Records;

import android.util.Log;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Puree {
    private static final String TAG = Puree.class.getSimpleName();

    private static boolean isInitialized = false;
    private static Gson gson;
    private static PureeStorage storage;

    private static Map<Key, List<PureeOutput>> sourceOutputMap = new HashMap<>();

    public static synchronized void initialize(PureeConfiguration conf) {
        if (isInitialized) {
            Log.w(TAG, "Puree has already been initialized");
            return;
        }

        gson = conf.getGson();
        storage = new PureeDbHelper(conf.getApplicationContext());
        sourceOutputMap = conf.getSourceOutputMap();

        for (List<PureeOutput> outputs : sourceOutputMap.values()) {
            for (PureeOutput output : outputs) {
                output.initialize(storage);
            }
        }

        isInitialized = true;
    }

    /**
     * Try to send log. This log is sent immediately or put into buffer (it's depending on output plugin).
     */
    public static void send(PureeLog log) {
        checkIfPureeHasInitialized();

        Key key = Key.from(log.getClass());
        List<PureeOutput> outputs = sourceOutputMap.get(key);
        if (outputs == null) {
            throw new IllegalStateException("No output plugin found for " + key);
        }
        for (PureeOutput output : outputs) {
            JsonObject jsonLog = (JsonObject) gson.toJsonTree(log);
            output.receive(jsonLog);
        }
    }

    /**
     * Try to flush all logs that are in buffer.
     */
    public static void flush() {
        checkIfPureeHasInitialized();
        for (List<PureeOutput> outputs : sourceOutputMap.values()) {
            for (PureeOutput output : outputs) {
                output.flush();
            }
        }
    }

    public static void dump() {
        LogDumper.out(getBufferedLogs());
    }

    /**
     * Get all logs that are in buffer.w
     */
    public static Records getBufferedLogs() {
        checkIfPureeHasInitialized();
        return storage.selectAll();
    }

    /**
     * Delete all logs that are in buffer.
     */
    public static void clear() {
        checkIfPureeHasInitialized();
        storage.clear();
    }

    private static synchronized void checkIfPureeHasInitialized() {
        if (!isInitialized) {
            throw new NotInitializedException();
        }
    }

    public static class NotInitializedException extends IllegalStateException {

    }
}

@@ -413,16 +413,51 @@
 l.Map;%0A%0A
+import javax.annotation.Nullable;%0A%0A
 public c
@@ -1306,32 +1306,404 @@
  = true;%0A    %7D%0A%0A
+    /**%0A     * Serialize a %7B@link PureeLog%7D into %7B@link JsonObject%7D with %7B@link Gson%7D%0A     */%0A    public static JsonObject serializeLog(PureeLog log) %7B%0A        return (JsonObject) gson.toJsonTree(log);%0A    %7D%0A%0A    @Nullable%0A    public static List%3CPureeOutput%3E getRegisteredOutputPlugins(PureeLog log) %7B%0A        return sourceOutputMap.get(Key.from(log.getClass()));%0A    %7D%0A%0A%0A
     /**%0A     * T
@@ -1904,103 +1904,66 @@
     
-Key key = Key.from(log.getClass());%0A        List%3CPureeOutput%3E outputs = sourceOutputMap.get(key
+List%3CPureeOutput%3E outputs = getRegisteredOutputPlugins(log
 );%0A 
@@ -2058,12 +2058,17 @@
 gin 
-foun
+registere
 d fo
@@ -2077,11 +2077,11 @@
 %22 + 
-key
+log
 );%0A 
@@ -2171,36 +2171,20 @@
 g = 
-(JsonObject) gson.toJsonTree
+serializeLog
 (log

make Puree.serializeLog() and Puree.getRegisteredOutputPllugins() public