package com.avg.zaap.crashlibrary.show.error.dialog;

import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Window;

import com.avg.zaap.crashlibrary.CrashLib;
import com.avg.zaap.crashlibrary.config.CrashLibConfig;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.support.membermodification.MemberMatcher.method;
import static org.powermock.api.support.membermodification.MemberMatcher.methods;

/**
 * A test class for {@link DialogActivity}.
 * <p>
 * Created by marek.osvald on 11.5.2016.
 */
@RunWith(PowerMockRunner.class)
@PrepareForTest({DialogActivity.class, android.os.Process.class})
public class DialogActivityTests {

    private static final int MOCK_MAIN_TEXT_ID = 123;
    private static final String MOCK_MAIN_TEXT = "mockMainText";

    private static final int MOCK_TITLE_ID = 456;
    private static final String MOCK_TITLE = "mockTitle";

    private DialogActivity mDialogActivity;
    private Resources mResources;
    private AlertDialog.Builder mAlertDialogBuilder;
    private AlertDialog mAlertDialog;
    private Window mWindow = mock(Window.class);
    private View mDecorView = mock(View.class);

    private ArgumentCaptor<DialogInterface.OnDismissListener> mDismissArgumentCaptor;

    @Before
    public void setUp() throws Exception {
        mDismissArgumentCaptor = ArgumentCaptor.forClass(DialogInterface.OnDismissListener.class);

        PowerMockito.suppress(methods(AppCompatActivity.class, "onCreate"));
        PowerMockito.suppress(methods(AppCompatActivity.class, "setContentView"));
        PowerMockito.suppress(methods(AppCompatActivity.class, "finish"));
        PowerMockito.suppress(methods(AppCompatActivity.class, "overridePendingTransition"));

        mResources = mock(Resources.class);
        PowerMockito.replace(method(AppCompatActivity.class, "getResources")).with(new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return mResources;
            }
        });

        when(mWindow.getDecorView()).thenReturn(mDecorView);
        PowerMockito.replace(method(AppCompatActivity.class, "getWindow")).with(new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return mWindow;
            }
        });

        //noinspection ResourceType
        when(mResources.getString(MOCK_MAIN_TEXT_ID)).thenReturn(MOCK_MAIN_TEXT);
        //noinspection ResourceType
        when(mResources.getString(MOCK_TITLE_ID)).thenReturn(MOCK_TITLE);

        mAlertDialogBuilder = mock(AlertDialog.Builder.class);
        mAlertDialog = mock(AlertDialog.class);

        when(mAlertDialogBuilder.setTitle(MOCK_TITLE)).thenReturn(mAlertDialogBuilder);
        when(mAlertDialogBuilder.setMessage(MOCK_MAIN_TEXT)).thenReturn(mAlertDialogBuilder);
        when(mAlertDialogBuilder.setPositiveButton(android.R.string.ok, null)).thenReturn(mAlertDialogBuilder);
        when(mAlertDialogBuilder.setOnDismissListener(mDismissArgumentCaptor.capture())).thenReturn(mAlertDialogBuilder);
        when(mAlertDialogBuilder.create()).thenReturn(mAlertDialog);

        initCrashLibConfig();

        IDialogActivityFactory factory = new IDialogActivityFactory() {
            @Override
            public AlertDialog.Builder getAlertDialog(Context context) {
                return mAlertDialogBuilder;
            }
        };

        mDialogActivity = spy(new DialogActivity(factory));
    }

    @Test
    public void onCreate_ok_setsTextsSetsOnClickDismissShowsDialog() throws Exception {
        // act
        mDialogActivity.onCreate(null);
        mDismissArgumentCaptor.getValue().onDismiss(mAlertDialog);

        // assert
        verify(mDecorView, times(1)).setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
        verify(mAlertDialogBuilder, times(1)).setTitle(MOCK_TITLE);
        verify(mAlertDialogBuilder, times(1)).setMessage(MOCK_MAIN_TEXT);
        verify(mAlertDialogBuilder, times(1)).create();
        verify(mAlertDialog, times(1)).show();
        verify(mDialogActivity, times(1)).finish();
        verify(mDialogActivity, times(1)).overridePendingTransition(0, 0);
    }

    private void initCrashLibConfig() {
        final CrashLibConfig crashLibConfig = new CrashLibConfig.Builder()
                .errorMessage(MOCK_TITLE_ID)
                .errorDetails(MOCK_MAIN_TEXT_ID)
                .build();

        Whitebox.setInternalState(CrashLib.class, "sConfig", crashLibConfig);
    }
}
