package jrummikub.control;

import jrummikub.control.network.ConnectionControl;
import jrummikub.control.network.NetworkControl;
import jrummikub.model.GameSettings;
import jrummikub.model.GameState;
import jrummikub.model.IRoundState;
import jrummikub.util.Connection;
import jrummikub.util.IListener;
import jrummikub.util.IListener1;
import jrummikub.util.IListener3;
import jrummikub.util.LoginData;
import jrummikub.view.IQuitWarningPanel.QuitMode;
import jrummikub.view.IView;
import jrummikub.view.IView.BottomPanelType;

/**
 * The application control controls the settings for a new games and create the
 * game control
 */
public class ApplicationControl {
	private SettingsControl settingsControl;
	private LoginControl loginControl;
	private NetworkControl networkControl;
	private SaveControl saveControl;
	private GameControl gameControl;
	private Connection tempConnection;

	private IView view;

	/**
	 * Creates a new application control
	 * 
	 * @param view
	 *          the view to use
	 */
	public ApplicationControl(final IView view) {
		this.view = view;
		saveControl = new SaveControl(view);

		view.getMenuNewGameEvent().add(new IListener() {
			@Override
			public void handle() {
				view.getQuitWarningPanel().setMode(QuitMode.QUIT_GAME);
				view.showQuitWarningPanel(true);
				tempConnection = view.getQuitWarningPanel().getQuitEvent()
						.add(new IListener() {
							@Override
							public void handle() {
								abortControls();
								startApplication();
								view.showQuitWarningPanel(false);
								tempConnection.remove();
							}
						});
			}
		});
		view.getMenuQuitEvent().add(new IListener() {
			@Override
			public void handle() {
				if (gameControl == null) {
					System.exit(0);
				} else {
					view.getQuitWarningPanel().setMode(QuitMode.QUIT_PROCESS);
					view.showQuitWarningPanel(true);
					view.getQuitWarningPanel().getQuitEvent().add(new IListener() {
						@Override
						public void handle() {
							System.exit(0);
						}
					});
				}
			}
		});

		view.getQuitEvent().add(new IListener() {
			@Override
			public void handle() {
				if (gameControl == null) {
					System.exit(0);
				} else {
					view.getQuitWarningPanel().setMode(QuitMode.QUIT_PROCESS);
					view.showQuitWarningPanel(true);
					view.getQuitWarningPanel().getQuitEvent().add(new IListener() {
						@Override
						public void handle() {
							System.exit(0);
						}
					});
				}
			}
		});

		view.getQuitWarningPanel().getCancelEvent().add(new IListener() {
			@Override
			public void handle() {
				view.showQuitWarningPanel(false);
			}
		});

		view.getNetworkGameEvent().add(new IListener() {
			@Override
			public void handle() {
				abortControls();

				createLoginControl();
			}
		});

		saveControl.getLoadEvent().add(
				new IListener3<GameSettings, GameState, IRoundState>() {
					@Override
					public void handle(GameSettings settings, GameState gameState,
							IRoundState roundState) {
						abortControls();
						gameControl = new GameControl(settings, saveControl, view);
						addGameControlListeners(gameControl);
						gameControl.continueGame(gameState, roundState);
					}
				});
		saveControl.getLoadErrorEvent().add(new IListener() {
			@Override
			public void handle() {
				view.showLoadingError();
			}
		});
	}

	private void createLoginControl() {
		loginControl = new LoginControl(view);
		loginControl.getLoginEvent().add(new IListener1<LoginData>() {
			@Override
			public void handle(LoginData loginData) {
				createNetworkControl(loginData);
			}
		});
		loginControl.getCancelEvent().add(new IListener() {
			@Override
			public void handle() {
				startApplication();
			}
		});
		loginControl.startLogin();
	}

	private void abortControls() {
		if (settingsControl != null) {
			settingsControl.abort();
			settingsControl = null;
		}

		if (gameControl != null) {
			gameControl.abortGame();
			gameControl = null;
		}

		if (loginControl != null) {
			loginControl.abort();
			loginControl = null;
		}

		if (networkControl != null) {
			networkControl.abort();
			networkControl = null;
		}
	}

	/**
	 * Starts the application by showing the game settings dialog panel
	 */
	public void startApplication() {
		view.showSidePanel(false);
		view.showScorePanel(false);
		view.setBottomPanel(BottomPanelType.START_GAME_PANEL);
		saveControl.setGameSettings(null);
		saveControl.setGameState(null);

		settingsControl = new SettingsControl(view, new GameSettings());
		view.enableSave(false);

		settingsControl.getStartGameEvent().add(new IListener1<GameSettings>() {
			@Override
			public void handle(GameSettings settings) {
				view.enableSave(true);
				settingsControl = null;

				saveControl.setGameSettings(settings);

				gameControl = new GameControl(settings, saveControl, view);
				addGameControlListeners(gameControl);

				gameControl.startGame();
			}
		});
		settingsControl.startSettings();
	}

	private void addGameControlListeners(GameControl gameControl) {
		gameControl.getEndOfGameEvent().add(new IListener() {
			@Override
			public void handle() {
				startApplication();
			}
		});
	}

	private void createNetworkControl(LoginData loginData) {
		ConnectionControl connectionControl = new ConnectionControl(loginData);
		networkControl = new NetworkControl(loginData, connectionControl, saveControl, view);

		networkControl.getStopNetworkEvent().add(new IListener() {
			@Override
			public void handle() {
				startApplication();
			}
		});

		networkControl.getBackToLoginEvent().add(new IListener() {
			@Override
			public void handle() {
				networkControl = null;
				createLoginControl();
			}
		});

		networkControl.startNetwork();
	}
}
