package com.atlassian.bitbucket.mesh.util;

import com.atlassian.bitbucket.mesh.AbstractWiredTest;
import com.atlassian.bitbucket.mesh.TestHelper;
import com.atlassian.bitbucket.mesh.git.GrpcRepositoryService;
import com.atlassian.bitbucket.mesh.network.MeshManager;
import com.atlassian.bitbucket.mesh.repository.ManagedRepository;
import com.atlassian.bitbucket.mesh.rpc.v1.RpcGetRepositoryDetailsResponse;
import com.atlassian.bitbucket.mesh.test.annotation.Repo;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.Mockito;

import javax.annotation.Resource;

import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.inOrder;

public class MethodCallHookTest extends AbstractWiredTest {

    @Resource
    private MethodCallHook methodCallHook;

    @Resource
    private TestHelper testHelper;

    @Repo
    private ManagedRepository repository;

    @Resource
    private MeshManager meshManager;

    @Test
    @Ignore //Only for testing utility class, doesn't need to run for regular func tests
    public void test() {
        Runnable before1 = Mockito.mock(Runnable.class);
        Runnable after1 = Mockito.mock(Runnable.class);
        Runnable before2 = Mockito.mock(Runnable.class);
        Runnable after2 = Mockito.mock(Runnable.class);

        methodCallHook.onExecutionOnce(GrpcRepositoryService.class, "getDetails", handler -> {
            before1.run();
            Object proceed = handler.proceed();
            after1.run();
            return proceed;
        });

        methodCallHook.onExecutionOnce(GrpcRepositoryService.class, "getDetails", handler -> {
            before2.run();
            Object proceed = handler.proceed();
            after2.run();
            return proceed;
        });

        RpcGetRepositoryDetailsResponse details = testHelper.getDetails(meshManager.getLocalNode(), repository.getId());

        assertNotNull(details);
        InOrder inOrder = inOrder(before1, after1, before2, after2);
        inOrder.verify(before1).run();
        inOrder.verify(before2).run();
        inOrder.verify(after2).run();
        inOrder.verify(after1).run();
    }
}
