package org.amc.game.chessserver.observers;

import org.amc.game.GameObserver;
import org.amc.game.chess.ChessGame;
import org.amc.game.chess.ChessGame.GameState;
import org.amc.game.chessserver.MessageType;
import org.amc.game.chessserver.AbstractServerChessGame;
import org.amc.game.chessserver.AbstractServerChessGame.ServerGameStatus;
import org.amc.game.chessserver.StompController;
import org.amc.util.Subject;
import org.apache.log4j.Logger;
import org.springframework.messaging.simp.SimpMessagingTemplate;

import java.util.HashMap;
import java.util.Map;

public class GameStateListener extends GameObserver {

    private static final Logger logger = Logger.getLogger(GameStateListener.class);
    
    /** 
     * STOMP messaging object to send stomp message to objects
     */
    private final SimpMessagingTemplate template;

    /**
     * STOMP message subscription destination
     */
    static final String MESSAGE_DESTINATION = "/topic/updates";
    
    public GameStateListener(SimpMessagingTemplate template) {
        this.template = template;
    }
    
    /**
     * Called by Model(ObservableChessGame) on change
     * 
     * Converts a ChessBoard to a JSON String and sends it
     * to the subscribed clients
     */
    @Override
    public void update(Subject subject, Object message) {
        if(subject instanceof AbstractServerChessGame) {
            AbstractServerChessGame serverChessGame = (AbstractServerChessGame)subject;
            if (message instanceof ChessGame.GameState) {
                GameState gameState = (GameState) message;
                sendMessage(serverChessGame, gameState.toString());
                logGameState(gameState);   
            } else if(message instanceof AbstractServerChessGame.ServerGameStatus) {
                ServerGameStatus status = (ServerGameStatus)message;
                if(status == ServerGameStatus.FINISHED) {
                    sendMessage(serverChessGame, serverChessGame.getChessGame().getGameState().toString());
                }
            }
        }
    }
    
    private void sendMessage(AbstractServerChessGame serverChessGame, String message) {
        this.template.convertAndSend(getMessageDestination(serverChessGame), message, getDefaultHeaders()); 
        logger.debug("Message sent to" + getMessageDestination(serverChessGame));
    }
    
    private String getMessageDestination(AbstractServerChessGame serverChessGame) {
        return String.format("%s/%d", MESSAGE_DESTINATION, serverChessGame.getUid());
    }
    
    private Map<String,Object> getDefaultHeaders(){
        Map<String,Object> headers = new HashMap<String, Object>();
        headers.put(StompController.MESSAGE_HEADER_TYPE, MessageType.STATUS);
        return headers;
    }
    
    private void logGameState(GameState gameState){
        switch(gameState){
        
        case BLACK_CHECKMATE:
            logger.info("White Player has won");
            break;
            
        case WHITE_CHECKMATE:
            logger.info("Black Player has won");
            break;
            
        case STALEMATE:
            logger.info("Game has ended in a draw");
            break;
            
        default:
            break;
        }
    }

}

@@ -38,16 +38,84 @@
 rvers;%0A%0A
+import org.amc.DAOException;%0Aimport org.amc.dao.ServerChessGameDAO;%0A
 import o
@@ -136,24 +136,24 @@
 meObserver;%0A
-
 import org.a
@@ -506,24 +506,140 @@
 g4j.Logger;%0A
+import org.springframework.beans.factory.annotation.Autowired;%0Aimport org.springframework.context.annotation.Scope;%0A
 import org.s
@@ -690,16 +690,65 @@
 emplate;
+%0Aimport org.springframework.stereotype.Component;
 %0A%0Aimport
@@ -790,16 +790,138 @@
 l.Map;%0A%0A
+import javax.annotation.Resource;%0Aimport javax.persistence.OptimisticLockException;%0A%0A@Component%0A@Scope(value=%22prototype%22)%0A
 public c
@@ -1132,24 +1132,39 @@
 cts%0A     */%0A
+    @Autowired%0A
     private 
@@ -1163,22 +1163,16 @@
 private 
-final 
 SimpMess
@@ -1194,16 +1194,72 @@
 emplate;
+%0A    %0A    private ServerChessGameDAO serverChessGameDAO;
 %0A%0A    /*
@@ -1416,75 +1416,11 @@
 ner(
-SimpMessagingTemplate template) %7B%0A        this.template = template;
+) %7B
 %0A   
@@ -1423,24 +1423,34 @@
 %0A    %7D%0A    %0A
+    %0A    %0A
     /**%0A    
@@ -2365,32 +2365,94 @@
 ().toString());%0A
+                    saveGameStateInDatabase(serverChessGame);%0A
                 
@@ -3663,11 +3663,625 @@
 %7D%0A    %7D%0A
+    %0A    private void saveGameStateInDatabase(AbstractServerChessGame serverChessGame) %7B%0A        try %7B%0A            serverChessGameDAO.saveServerChessGame(serverChessGame);%0A        %7D catch (DAOException %7C OptimisticLockException de) %7B%0A            logger.error(de);%0A        %7D%0A    %7D%0A    %0A    @Resource(name = %22myServerChessGameDAO%22)%0A    public void setServerChessGameDAO(ServerChessGameDAO serverChessGameDAO) %7B%0A        this.serverChessGameDAO = serverChessGameDAO;%0A    %7D%0A    %0A    public void setSimpMessagingTemplate(SimpMessagingTemplate simpMessagingTemplate) %7B%0A        this.template = simpMessagingTemplate;%0A    %7D
 %0A%7D%0A

modify GameStateListener