package com.avg.zaap.crashlibrary.core.logger;

import android.util.Log;

import com.avg.zaap.crashlibrary.BuildConfig;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.verifyStatic;

/**
 * A test class for {@link DefaultLogger}.
 * <p/>
 * Created by marek.osvald on 2.5.2016.
 */
@RunWith(PowerMockRunner.class)
@PrepareForTest({BuildConfig.class, Log.class})
public class DefaultLoggerTests {

    private static final String TAG = "tag";
    private static final String MESSAGE = "message";
    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
    private static final Throwable THROWABLE = mock(Throwable.class);

    private ILogger mDefaultLogger;

    @Before
    public void setUp() throws Exception {
        mDefaultLogger = new DefaultLogger();
        mockStatic(Log.class);
    }

    @Test
    public void v_release_doesNotLog() throws Exception {
        // act
        mDefaultLogger.v(TAG, MESSAGE);

        // assert
        if (BuildConfig.DEBUG) {
            verifyStatic(times(1));
            Log.v(TAG, MESSAGE);
        } else {
            verifyStatic(never());
            Log.v(anyString(), anyString());
        }
    }

    @Test
    public void v_releaseThrowable_doesNotLog() throws Exception {
        // act
        mDefaultLogger.v(TAG, MESSAGE, THROWABLE);

        // assert
        if (BuildConfig.DEBUG) {
            verifyStatic(times(1));
            Log.v(TAG, MESSAGE, THROWABLE);
        } else {
            verifyStatic(never());
            Log.v(anyString(), anyString(), any(Throwable.class));
        }
    }

    @Test
    public void d_release_doesNotLog() throws Exception {
        // act
        mDefaultLogger.d(TAG, MESSAGE);

        // assert
        if (BuildConfig.DEBUG) {
            verifyStatic(times(1));
            Log.d(TAG, MESSAGE);
        } else {
            verifyStatic(never());
            Log.d(anyString(), anyString());
        }
    }

    @Test
    public void d_releaseThrowable_doesNotLog() throws Exception {
        // act
        mDefaultLogger.d(TAG, MESSAGE, THROWABLE);

        // assert
        if (BuildConfig.DEBUG) {
            verifyStatic(times(1));
            Log.d(TAG, MESSAGE, THROWABLE);
        } else {
            verifyStatic(never());
            Log.d(anyString(), anyString(), any(Throwable.class));
        }
    }

    @Test
    public void i_release_doesNotLog() throws Exception {
        // act
        mDefaultLogger.i(TAG, MESSAGE);

        // assert
        if (BuildConfig.DEBUG) {
            verifyStatic(times(1));
            Log.i(TAG, MESSAGE);
        } else {
            verifyStatic(never());
            Log.i(anyString(), anyString());
        }
    }

    @Test
    public void i_releaseThrowable_doesNotLog() throws Exception {
        // act
        mDefaultLogger.i(TAG, MESSAGE, THROWABLE);

        // assert
        if (BuildConfig.DEBUG) {
            verifyStatic(times(1));
            Log.i(TAG, MESSAGE, THROWABLE);
        } else {
            verifyStatic(never());
            Log.i(anyString(), anyString(), any(Throwable.class));
        }
    }

    @Test
    public void w_release_doesNotLog() throws Exception {
        // act
        mDefaultLogger.w(TAG, MESSAGE);

        // assert
        if (BuildConfig.DEBUG) {
            verifyStatic(times(1));
            Log.w(TAG, MESSAGE);
        } else {
            verifyStatic(never());
            Log.w(anyString(), anyString());
        }
    }

    @Test
    public void w_releaseThrowable_doesNotLog() throws Exception {
        // act
        mDefaultLogger.w(TAG, THROWABLE);

        // assert
        if (BuildConfig.DEBUG) {
            verifyStatic(times(1));
            Log.w(TAG, THROWABLE);
        } else {
            verifyStatic(never());
            Log.w(anyString(), any(Throwable.class));
        }
    }

    @Test
    public void w_releaseMessageThrowable_doesNotLog() throws Exception {
        // act
        mDefaultLogger.w(TAG, MESSAGE, THROWABLE);

        // assert
        if (BuildConfig.DEBUG) {
            verifyStatic(times(1));
            Log.w(TAG, MESSAGE, THROWABLE);
        } else {
            verifyStatic(never());
            Log.w(anyString(), anyString(), any(Throwable.class));
        }
    }

    @Test
    public void e_release_doesNotLog() throws Exception {
        // act
        mDefaultLogger.e(TAG, MESSAGE);

        // assert
        if (BuildConfig.DEBUG) {
            verifyStatic(times(1));
            Log.e(TAG, MESSAGE);
        } else {
            verifyStatic(never());
            Log.e(anyString(), anyString());
        }
    }

    @Test
    public void e_releaseThrowable_doesNotLog() throws Exception {
        // act
        mDefaultLogger.e(TAG, MESSAGE, THROWABLE);

        // assert
        if (BuildConfig.DEBUG) {
            verifyStatic(times(1));
            Log.e(TAG, MESSAGE, THROWABLE);
        } else {
            verifyStatic(never());
            Log.e(anyString(), anyString(), any(Throwable.class));
        }
    }

    @Test
    public void wtf_release_doesNotLog() throws Exception {
        // act
        mDefaultLogger.wtf(TAG, MESSAGE);

        // assert
        if (BuildConfig.DEBUG) {
            verifyStatic(times(1));
            Log.wtf(TAG, MESSAGE);
        } else {
            verifyStatic(never());
            Log.wtf(anyString(), anyString());
        }
    }

    @Test
    public void wtf_releaseThrowable_doesNotLog() throws Exception {
        // act
        mDefaultLogger.wtf(TAG, THROWABLE);

        // assert
        if (BuildConfig.DEBUG) {
            verifyStatic(times(1));
            Log.wtf(TAG, THROWABLE);
        } else {
            verifyStatic(never());
            Log.wtf(anyString(), any(Throwable.class));
        }
    }

    @Test
    public void wtf_releaseMessageThrowable_doesNotLog() throws Exception {
        // act
        mDefaultLogger.wtf(TAG, MESSAGE, THROWABLE);

        // assert
        if (BuildConfig.DEBUG) {
            verifyStatic(times(1));
            Log.wtf(TAG, MESSAGE, THROWABLE);
        } else {
            verifyStatic(never());
            Log.wtf(anyString(), anyString(), any(Throwable.class));
        }
    }

}
