package com.miguelgaeta.bootstrap.mg_preference;

import android.content.Context;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.KryoException;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.miguelgaeta.bootstrap.mg_log.MGLog;

import org.objenesis.strategy.StdInstantiatorStrategy;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.lang.reflect.Type;

import lombok.NonNull;

/**
 * Created by Miguel Gaeta on 9/25/15.
 */
class MGPrefStoreTypeByeStream extends MGPreferenceStore {

    private Context context;

    private ThreadLocal<Kryo> kryos;

    private boolean allowClassesWithNoConstructors;

    public void init(@NonNull Context context, boolean allowClassesWithNoConstructors) {

        this.context = context;

        this.allowClassesWithNoConstructors = allowClassesWithNoConstructors;
    }

    @Override
    public void init(@NonNull Context context) {

        init(context, true);
    }

    @Override
    public Object get(@NonNull String key, Type typeOfObject, boolean versioned) {

        final File file = new File(context.getFilesDir() + "/" + getFileName(0, key));

        if (file.exists()) {

            try {

                final Input input = new Input(new FileInputStream(file));

                final Object output = getKryo().readClassAndObject(input);

                input.close();

                return output;

            } catch (KryoException | FileNotFoundException e) {

                MGLog.i(e, "Unable to deserialize for key: " + key);
            }
        }

        return null;
    }

    @Override
    public void set(@NonNull String key, Object value, Type typeOfObject, boolean versioned) {

        try {
            final Output output = new Output(context
                .openFileOutput(getFileName(0, key), Context.MODE_PRIVATE));

            getKryo().writeClassAndObject(output, value);

            output.close();

        } catch (FileNotFoundException e) {

            MGLog.i(e, "File not found for key: " + key);
        }
    }

    @Override
    public void clear() {

        // TODO
    }

    private Kryo getKryo() {

        if (kryos == null) {
            kryos = new ThreadLocal<Kryo>() {

                protected Kryo initialValue() {

                    final Kryo kryo = new Kryo();

                    if (allowClassesWithNoConstructors) {

                        // Use the default instantiation, but attempt to use JVM trickery if that fails.
                        kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
                    }

                    return kryo;
                }
            };
        }

        return kryos.get();
    }
}

@@ -246,24 +246,94 @@
 .io.Output;%0A
+import com.miguelgaeta.bootstrap.mg_lifecycle.MGLifecycleApplication;%0A
 import com.m
@@ -543,24 +543,46 @@
 lect.Type;%0A%0A
+import lombok.Getter;%0A
 import lombo
@@ -708,331 +708,139 @@
     
-private Context context;%0A%0A    private ThreadLocal%3CKryo%3E kryos;%0A%0A    private boolean allowClassesWithNoConstructors;%0A%0A    public void init(@NonNull Context context, boolean allowClassesWithNoConstructors) %7B%0A%0A        this.context = c
+@Getter(lazy = true)%0A    private final Context context = MGLifecycleApplication.getC
 ontext
+()
 ;%0A%0A    
-  
-  this.allowClassesWithNoConstructors = allowClassesWithNoConstructors;%0A    %7D
+private ThreadLocal%3CKryo%3E kryos;
 %0A%0A  
@@ -905,37 +905,8 @@
  %7B%0A%0A
-        init(context, true);%0A
     
@@ -1041,23 +1041,28 @@
 ew File(
-c
+getC
 ontext
+()
 .getFile
@@ -1723,32 +1723,20 @@
 put(
-c
+getC
 ontext
-%0A                
+()
 .ope
@@ -2275,71 +2275,8 @@
 );%0A%0A
-                    if (allowClassesWithNoConstructors) %7B%0A%0A    
     
@@ -2372,20 +2372,16 @@
  fails.%0A
-    
         
@@ -2494,30 +2494,8 @@
 )));
-%0A                    %7D
 %0A%0A  

Use application context to prevent threading errors until API is revised.