package cz.cuni.amis.pogamut.ut2004.server;

import com.google.inject.Inject;

import cz.cuni.amis.pogamut.base.agent.AgentStateType;
import cz.cuni.amis.pogamut.base.agent.IAgent;
import cz.cuni.amis.pogamut.base.agent.jmx.AgentJMXProxy;
import cz.cuni.amis.pogamut.base.agent.worldview.EventDrivenWorldView;
import cz.cuni.amis.pogamut.base.agent.worldview.IStartableWorldView;
import cz.cuni.amis.pogamut.base.agent.worldview.WorldEventListener;
import cz.cuni.amis.pogamut.base.communication.commands.CommandSerializer;
import cz.cuni.amis.pogamut.base.communication.commands.ICommandSerializer;
import cz.cuni.amis.pogamut.base.factory.guice.AgentScoped;
import cz.cuni.amis.pogamut.base.utils.logging.AgentLogger;
import cz.cuni.amis.pogamut.ut2004.agent.worldview.DefaultUT2004WorldView;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.SetGameSpeed;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.StartPlayers;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Player;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.PlayerJoinsGame;
import cz.cuni.amis.pogamut.ut2004.communication.translator.events.MapListObtained;
import cz.cuni.amis.pogamut.ut2004.communication.translator.events.MutatorListObtained;
import cz.cuni.amis.utils.collections.ObservableCollection;
import cz.cuni.amis.utils.collections.TranslatedObservableCollection;
import cz.cuni.amis.utils.flag.FlagListener;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.MalformedObjectNameException;

// TODO: [Ruda] implement the class
@AgentScoped
public class UT2004Server extends AbstractUT2004Server<IStartableWorldView> implements IUT2004Server {

    ObservableCollection<IAgent> pogamutAgents = null;

    @Inject
    public UT2004Server(AgentLogger logger, DefaultUT2004WorldView worldView, ICommandSerializer act) {
        super(logger, worldView, act);
        pogamutAgents = new TranslatedObservableCollection<IAgent, Player>(players) {

            /**
             * Create JMX proxy for the agent.
             */
            @Override
            protected IAgent translate(Player obj) {
                try {
                    // TODO check right param
                    return new AgentJMXProxy(obj.getJmx());
                } catch (Exception ex) {
                    Logger.getLogger(UT2004Server.class.getName()).log(Level.SEVERE, null, ex);
                    return null;
                }
            }
        };
    }
    protected WorldEventListener<PlayerJoinsGame> playerJoinsListener = null;
    protected WorldEventListener<MapListObtained> mapListListener = null;

    @Override
    protected void prePrepareServer() {

        // TODO change the players list on the fly
        /*getWorldView().addListener(PlayerJoinsGame.class, playerJoinsListener = new WorldEventListener<PlayerJoinsGame>() {

        public void notify(PlayerJoinsGame event) {
        // TODO
        players.add(null);
        }
        });
         */
        // TODO player left


        // mutators list
        getWorldView().addListener(MutatorListObtained.class, new WorldEventListener<MutatorListObtained>() {

            public void notify(MutatorListObtained event) {
                mutators = event.getMutators();
            }
        });

        // TODO where to get gamespeed?
        // gamespeed
        gameSpeed.addListener(new FlagListener<Double>() {

            public void flagChanged(Double changedValue) {
                getAct().act(new SetGameSpeed(changedValue));
            }
        });

        // maps
        getWorldView().addListener(MapListObtained.class, mapListListener = new WorldEventListener<MapListObtained>() {

            public void notify(MapListObtained event) {
                maps = event.getMaps();

                // after this the server is ready
                setAgentState(AgentStateType.RUNNING, "Control server connection is up and running.");
                // start tracking connected players
                getAct().act(new StartPlayers(true, true, true));
            }
        });

        // TODO: [Ruda] here you may provide a custom hooks to the world view (but you may do this in constructor as well)
        //              this is called after the HELLO_CONTROL_SERVER is received
    }
}
