package org.amc.game.chessserver.observers;

import static org.mockito.Mockito.*;
import static org.junit.Assert.*;

import org.amc.DAOException;
import org.amc.dao.ServerChessGameDAO;
import org.amc.game.chess.ChessBoard;
import org.amc.game.chess.ChessGame;
import org.amc.game.chess.ChessGameFactory;
import org.amc.game.chess.ChessGamePlayer;
import org.amc.game.chess.Colour;
import org.amc.game.chess.HumanPlayer;
import org.amc.game.chess.RealChessGamePlayer;
import org.amc.game.chessserver.ServerChessGame;
import org.amc.game.chessserver.TwoViewServerChessGame;
import org.amc.game.chessserver.observers.GameStateListener;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.messaging.simp.SimpMessagingTemplate;

public class GameStateListenerTest {

    private GameStateListener listener;
    private ChessGamePlayer whitePlayer;
    private ChessGamePlayer blackPlayer;
    private ServerChessGame serverGame;
    private SimpMessagingTemplate template;
    private static final long GAME_UID = 1234l;
    private ArgumentCaptor<String> destinationArgument;
    private ArgumentCaptor<Object> messageArgument;
    private ChessGameFactory chessGameFactory;
    
    @Mock
    ServerChessGameDAO serverChessGameDAO;
    
    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        whitePlayer = new RealChessGamePlayer(new HumanPlayer("White Player"), Colour.WHITE);
        blackPlayer = new RealChessGamePlayer(new HumanPlayer("Black Player"), Colour.BLACK);
        template = mock(SimpMessagingTemplate.class);
        
        chessGameFactory = new ChessGameFactory() {
            @Override
            public ChessGame getChessGame(ChessBoard board, ChessGamePlayer playerWhite,
                            ChessGamePlayer playerBlack) {
                return new ChessGame(board, playerWhite, playerBlack);
            }
        };
        
        serverGame = new TwoViewServerChessGame(GAME_UID, whitePlayer);
        serverGame.setChessGameFactory(chessGameFactory);
        serverGame.addOpponent(blackPlayer);
        
        
        destinationArgument = ArgumentCaptor.forClass(String.class);
        messageArgument = ArgumentCaptor.forClass(Object.class);
    }

    @After
    public void tearDown() throws Exception {
    }

    @SuppressWarnings("unchecked")
    @Test
    public void test() throws DAOException {
        listener = new GameStateListener();
        listener.setGameToObserver(serverGame);
        listener.setSimpMessagingTemplate(template);

        listener.update(serverGame, ChessGame.GameState.RUNNING);
        verify(serverChessGameDAO, never()).saveServerChessGame(eq(serverGame));
        verify(template).convertAndSend(destinationArgument.capture(),messageArgument.capture(),anyMap());
        assertEquals(String.format(GameStateListener.MESSAGE_DESTINATION + "/%d",serverGame.getUid()), 
                        destinationArgument.getValue());
        
        assertEquals(ChessGame.GameState.RUNNING.toString(), messageArgument.getValue());
    }
    
    @SuppressWarnings("unchecked")
    @Test
    public void testSendCheckMateMessage() throws DAOException {
        listener = new GameStateListener();
        listener.setGameToObserver(serverGame);
        listener.setSimpMessagingTemplate(template);
        listener.setServerChessGameDAO(serverChessGameDAO);
        
        listener.update(serverGame, ServerChessGame.ServerGameStatus.FINISHED);
        verify(template, times(1)).convertAndSend(anyString(),anyObject(),anyMap());
        verify(serverChessGameDAO, times(1)).saveServerChessGame(eq(serverGame));
    }
    
    @SuppressWarnings("unchecked")
    @Test
    public void testMessageIsIgnored() throws DAOException {
        listener = new GameStateListener();
        listener.setGameToObserver(serverGame);
        listener.setSimpMessagingTemplate(template);
        listener.update(serverGame, null);
        verify(template, never()).convertAndSend(anyString(),anyObject(),anyMap());
        
        listener.update(null, ChessGame.GameState.RUNNING);
        verify(template, never()).convertAndSend(anyString(),anyObject(),anyMap());
        verify(serverChessGameDAO, never()).saveServerChessGame(eq(serverGame));
    }

}

@@ -1071,47 +1071,8 @@
     
-private SimpMessagingTemplate template;
 %0A   
@@ -1290,16 +1290,24 @@
 ock%0A    
+private 
 ServerCh
@@ -1338,24 +1338,83 @@
 meDAO;%0A    %0A
+    @Mock%0A    private SimpMessagingTemplate template;%0A    %0A
     @Before%0A
@@ -1508,16 +1508,262 @@
         
+destinationArgument = ArgumentCaptor.forClass(String.class);%0A        messageArgument = ArgumentCaptor.forClass(Object.class);%0A        setUpServerChessGame();%0A        %0A        setUpListener();%0A    %7D%0A%0A    private void setUpServerChessGame() %7B%0A    %09
 whitePla
@@ -1942,75 +1942,9 @@
     
-    template = mock(SimpMessagingTemplate.class);%0A        %0A        
+%09
 ches
@@ -2433,24 +2433,26 @@
 layer);%0A    
+%7D%0A
     %0A       
@@ -2452,144 +2452,238 @@
     
-    %0A        destinationArgument = ArgumentCaptor.forClass(String.class);%0A        messageArgument = ArgumentCaptor.forClass(Object.class
+private void setUpListener() %7B%0A    %09listener = new GameStateListener();%0A        listener.setGameToObserver(serverGame);%0A        listener.setSimpMessagingTemplate(template);%0A        listener.setServerChessGameDAO(serverChessGameDAO
 );%0A 
@@ -2683,24 +2683,28 @@
 DAO);%0A    %7D%0A
+    
 %0A    @After%0A
@@ -2850,154 +2850,8 @@
 n %7B%0A
-        listener = new GameStateListener();%0A        listener.setGameToObserver(serverGame);%0A        listener.setSimpMessagingTemplate(template);%0A%0A
     
@@ -3485,222 +3485,8 @@
 n %7B%0A
-        listener = new GameStateListener();%0A        listener.setGameToObserver(serverGame);%0A        listener.setSimpMessagingTemplate(template);%0A        listener.setServerChessGameDAO(serverChessGameDAO);%0A        %0A
     
@@ -3849,153 +3849,8 @@
 n %7B%0A
-        listener = new GameStateListener();%0A        listener.setGameToObserver(serverGame);%0A        listener.setSimpMessagingTemplate(template);%0A
     
@@ -4213,10 +4213,86 @@
 %0A    %7D%0A%0A
+    @Test%0A    public void promotionTest() throws DAOException %7B%0A    %09%0A    %7D%0A
 %7D%0A

refactor GameStateListenerTest