package com.cookpad.puree.outputs;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;

import com.cookpad.puree.Puree;
import com.cookpad.puree.PureeConfiguration;
import com.cookpad.puree.PureeLog;
import com.cookpad.puree.async.AsyncResult;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.support.test.InstrumentationRegistry;

import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

public class PureeBufferedOutputTest {

    ArrayList<String> logs = new ArrayList<>();

    BufferedOutput output;

    static class PvLog implements PureeLog {

        String name;

        public PvLog(String name) {
            this.name = name;
        }
    }

    @ParametersAreNonnullByDefault
    class BufferedOutput extends PureeBufferedOutput {

        public BufferedOutput(Handler handler) {
            super(handler);
        }

        @Override
        public void emit(JsonArray jsonArray, AsyncResult result) {
            for (JsonElement item : jsonArray) {
                logs.add(item.toString());
            }
            result.success();
        }

        @Nonnull
        @Override
        public String type() {
            return "buffered_output";
        }

        @Nonnull
        @Override
        public OutputConfiguration configure(OutputConfiguration conf) {
            conf.setFlushIntervalMillis(1);
            return conf;
        }
    }

    @Before
    public void setUp() throws Exception {
        Context context = InstrumentationRegistry.getTargetContext();
        Handler handler = new Handler(Looper.getMainLooper());

        output = new BufferedOutput(handler);
        Puree.initialize(new PureeConfiguration.Builder(context)
                .register(PvLog.class, output)
                .build());
        Puree.discardBufferedLogs();
    }

    @After
    public void tearDown() throws Exception {
        Puree.discardBufferedLogs();
    }

    @Test
    public void testPureeBufferedOutput() throws Exception {
        Puree.send(new PvLog("foo"));
        Puree.send(new PvLog("bar"));
        Puree.send(new PvLog("baz"));

        final CountDownLatch latch = new CountDownLatch(1);

        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                Puree.flush();
                return null;
            }

            @Override
            protected void onPostExecute(Void aVoid) {
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                latch.countDown();
            }
        }.execute();

        assertThat(latch.await(1, TimeUnit.SECONDS), is(true));

        assertThat(logs.size(), is(3));
        assertThat(logs.get(0), is("{\"name\":\"foo\"}"));
        assertThat(logs.get(1), is("{\"name\":\"bar\"}"));
        assertThat(logs.get(2), is("{\"name\":\"baz\"}"));
    }
}

@@ -104,40 +104,8 @@
 t;%0A%0A
-import com.cookpad.puree.Puree;%0A
 impo
@@ -180,16 +180,54 @@
 reeLog;%0A
+import com.cookpad.puree.PureeLogger;%0A
 import c
@@ -372,37 +372,8 @@
 xt;%0A
-import android.os.AsyncTask;%0A
 impo
@@ -506,90 +506,8 @@
 ist;
-%0Aimport java.util.concurrent.CountDownLatch;%0Aimport java.util.concurrent.TimeUnit;
 %0A%0Aim
@@ -803,16 +803,41 @@
 utput;%0A%0A
+    PureeLogger logger;%0A%0A
     stat
@@ -1935,24 +1935,25 @@
 ndler);%0A
+%0A
         
 Puree.in
@@ -1948,25 +1948,17 @@
     
-Puree.initialize(
+logger = 
 new 
@@ -2064,18 +2064,16 @@
 .build()
-);
 %0A       
@@ -2065,37 +2065,76 @@
 build()%0A        
-Puree
+        .createPureeLogger();%0A        logger
 .discardBuffered
@@ -2213,21 +2213,22 @@
         
-Puree
+logger
 .discard
@@ -2321,37 +2321,38 @@
 ption %7B%0A        
-Puree
+logger
 .send(new PvLog(
@@ -2360,37 +2360,38 @@
 foo%22));%0A        
-Puree
+logger
 .send(new PvLog(
@@ -2407,21 +2407,22 @@
         
-Puree
+logger
 .send(ne
@@ -2438,25 +2438,24 @@
 baz%22));%0A
-%0A
         
 final Co
@@ -2450,373 +2450,25 @@
     
-final CountDownLatch latch = new CountDownLatch(1);%0A%0A        new AsyncTask%3CVoid, Void, Void%3E() %7B%0A            @Override%0A            protected Void doInBackground(Void... params) %7B%0A                Puree.flush();%0A                return null;%0A            %7D%0A%0A            @Override%0A            protected void onPostExecute(Void aVoid) %7B%0A                try %7B%0A            
+logger.flush();%0A%0A
     
@@ -2488,256 +2488,12 @@
 eep(
-700);%0A                %7D catch (InterruptedException e) %7B%0A                    e.printStackTrace();%0A                %7D%0A                latch.countDown();%0A            %7D%0A        %7D.execute();%0A%0A        assertThat(latch.await(1, TimeUnit.SECONDS), is(true)
+1000
 );%0A%0A

refactor tests