package ch.sahits.game.graphic.display.gameplay;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import org.apache.log4j.Logger;
import ch.sahits.game.event.EViewChangeEvent;
import ch.sahits.game.event.Event;
import ch.sahits.game.event.IEventListener;
import ch.sahits.game.event.ViewChangeEvent;
import ch.sahits.game.graphic.display.dialog.OpenPatricianGameDialog;
import ch.sahits.game.graphic.display.gameplay.internal.EScene;
import ch.sahits.game.graphic.display.gameplay.internal.ISceneHandler;
import ch.sahits.game.graphic.display.gameplay.internal.MarketPlaceScenehandler;
import ch.sahits.game.graphic.display.gameplay.internal.PortSceneHandler;
import ch.sahits.game.graphic.display.gameplay.internal.SceneHandlerFactory;
import ch.sahits.game.graphic.display.model.CityPlayerProxy;
import ch.sahits.game.graphic.display.model.ViewChangeCityPlayerProxy;
import ch.sahits.game.graphic.display.notice.ENoticeItem;
import ch.sahits.game.graphic.image.DisplayImageDIResolver;
import ch.sahits.game.graphic.image.IDataImageLoader;
import ch.sahits.game.graphic.image.IImageLoader;
import ch.sahits.game.image.EScaling;
import ch.sahits.game.image.IImageUtilities;
import ch.sahits.game.image.ImageScaleState;
import ch.sahits.game.image.Scaling;
import ch.sahits.game.openpatrician.client.IClient;
import ch.sahits.game.openpatrician.model.ship.IShip;
import ch.sahits.game.rendering.AbstractRenderPart;
/**
* This represents the main game screen
* @author Andi Hotz, (c) Sahits GmbH, 2011
* Created on Sep 30, 2011
*
*/
public class MainView extends AbstractRenderPart implements IEventListener, IUpdatableDialog {
private static final Logger logger = Logger.getLogger(MainView.class);
/** This image holds the background of the currently rendered View */
private BufferedImage img;
private OpenPatricianGameDialog dialog=null;
private final static String[] imageNames = {"fringe", "waxseal","sealingWaxFlattend",
"barrel_icon","bale_icon","coin_icon","plusIcon","minusIcon"};
/**
* Use low level byte to indicate what is displayed instead of an enum.
*/
private EScene viewState = EScene.PORT;
/** Model of the city currently displayed. May be null if no city is displayed */
private CityPlayerProxy city;
private final IImageUtilities imageUtils;
private final IDataImageLoader xmlLoader;
private final IImageLoader loader;
/**
* Instantiate the main view with the port scene of the players home town
* @param rect
* @param loader
* @param cl
*/
public MainView(Rectangle rect, IImageLoader loader, IClient cl) {
super(rect);
DisplayImageDIResolver resolver = DisplayImageDIResolver.getInstance();
this.xmlLoader = resolver.getXMLImageLoader();
this.loader = loader;
imageUtils = resolver.getImageUtilities();
city = new CityPlayerProxy(cl.getPlayer().getHometown(), cl.getPlayer());
IShip ship = cl.getPlayer().getFleet().get(0);
city.arrive(ship);
logger.debug("MainView: "+rect);
ISceneHandler sceneHandler = SceneHandlerFactory.getSceneLoader(EScene.PORT, getBounds(), xmlLoader, resolver);
img = sceneHandler.init(resolver);
sceneHandler = SceneHandlerFactory.getSceneLoader(EScene.MARKET, getBounds(), xmlLoader, resolver);
sceneHandler.init(resolver); // do not update the image
resetDialog();
Event.add(this);
}
/**
* Scale the dialog so it has the correct proportions
*/
private void resetDialog() {
Dimension targetDim = new Dimension(getBounds().width*2/3, 600);
BufferedImage tmpImg = loader.getImage(imageNames[0]); // fringe
ImageScaleState state = new ImageScaleState(new Dimension(tmpImg.getWidth(), tmpImg.getHeight()), targetDim);
Scaling scaling = imageUtils.computeScaleFactor(targetDim, new Dimension(tmpImg.getWidth(), tmpImg.getHeight()), EScaling.DOWN);
state.setScaleFactor(scaling.getScaleFactor());
BufferedImage frame = imageUtils.scale(tmpImg, state);
loader.replaceSingleImage(imageNames[0], frame);
tmpImg = loader.getImage(imageNames[1]); // wax seal
loader.replaceSingleImage(imageNames[1], imageUtils.scale(tmpImg, state));
tmpImg = loader.getImage(imageNames[2]); // sealingWaxFlattend
loader.replaceSingleImage(imageNames[2], imageUtils.scale(tmpImg, state));
int height = loader.getImage(imageNames[2]).getHeight();
targetDim = new Dimension(height, height);
replaceImage(imageNames[3], targetDim); // barrel
replaceImage(imageNames[4], targetDim); // bale
replaceImage(imageNames[5], targetDim); // coin
tmpImg = loader.getImage(imageNames[6]); // plus icon
loader.replaceSingleImage(imageNames[6], imageUtils.scale(tmpImg, state));
tmpImg = loader.getImage(imageNames[7]); // minus icon
loader.replaceSingleImage(imageNames[7], imageUtils.scale(tmpImg, state));
}
/**
* Scale an image down to target dimension and replace it in the loader cache
* @param imgName
* @param targetDim
*/
private void replaceImage(String imgName, Dimension targetDim){
BufferedImage tmpImg = loader.getImage(imgName); // coin
ImageScaleState state = new ImageScaleState(new Dimension(tmpImg.getWidth(), tmpImg.getHeight()), targetDim);
Scaling scaling = imageUtils.computeScaleFactor(targetDim, new Dimension(tmpImg.getWidth(), tmpImg.getHeight()), EScaling.DOWN);
state.setScaleFactor(scaling.getScaleFactor());
tmpImg = imageUtils.scale(tmpImg, state);
loader.replaceSingleImage(imgName, tmpImg);
}
@Override
public void gameRender(Graphics gScr) {
Color oldColor = gScr.getColor();
gScr.drawImage(img, rect.x, rect.y, null);
if (dialog!=null){
dialog.gameRender(gScr);
}
gScr.setColor(oldColor);
}
@Override
public void gameUpdate(Event e, Object eventNotice) {
if (e instanceof ViewChangeEvent && ((ViewChangeEvent)e).getAddresse() == getClass() && eventNotice instanceof ViewChangeCityPlayerProxy){
ViewChangeCityPlayerProxy proxy = (ViewChangeCityPlayerProxy) eventNotice;
EViewChangeEvent changeEvent = proxy.getViewChangeEvent();
switch (changeEvent) {
case MAIN_VIEW_MARKET:
handleViewChange(EScene.MARKET);
break;
case MAIN_VIEW_PORT:
handleViewChange(EScene.PORT);
break;
default:
logger.debug("ViewChangeEvent "+changeEvent+" is not handled here");
}
} else {
if (canDelegateToSceneHandler(e, eventNotice) ){
DisplayImageDIResolver resolver = DisplayImageDIResolver.getInstance();
ISceneHandler handler = SceneHandlerFactory.getSceneLoader(viewState, getBounds(), xmlLoader, resolver);
handler.updateScene(e, eventNotice, city, this);
}
if (isDialogChange(e,eventNotice)){
handleDialogChange((ENoticeItem)eventNotice);
}
}
}
/**
* Update the dialog according to the indicated selection
* @param noticeItem
*/
private void handleDialogChange(ENoticeItem noticeItem) {
DisplayImageDIResolver resolver = DisplayImageDIResolver.getInstance();
switch (noticeItem) {
case MB_STOCK_PRICES:{
MarketPlaceScenehandler handler = (MarketPlaceScenehandler) SceneHandlerFactory.getSceneLoader(viewState, getBounds(), xmlLoader, resolver);
handler.displayTradingStockdialog(city, this);
break;
}
case MB_CONSUMPTION_PRODUCTION: {
MarketPlaceScenehandler handler = (MarketPlaceScenehandler) SceneHandlerFactory.getSceneLoader(viewState, getBounds(), xmlLoader, resolver);
handler.displayConsumtionProductionDialog(city, this);
break;
}
case TO_BALANCE:{
PortSceneHandler handler = (PortSceneHandler) SceneHandlerFactory.getSceneLoader(viewState, getBounds(), xmlLoader, resolver);
handler.displayTradingOfficeBalanceDialog(city, this);
break;
}
case TO_CONSUMPTION_PRODUCTION:{
PortSceneHandler handler = (PortSceneHandler) SceneHandlerFactory.getSceneLoader(viewState, getBounds(), xmlLoader, resolver);
handler.displayConsumtionProductionDialog(city, this);
break;
}
case TO_OFFICE_TRADING:
logger.debug("Should desplay dialog");
break;
case TO_PERSONAL:{
PortSceneHandler handler = (PortSceneHandler) SceneHandlerFactory.getSceneLoader(viewState, getBounds(), xmlLoader, resolver);
handler.displayTradingOfficePersonaldialog(city, this);
logger.debug("Should desplay dialog");
break;
}
case TO_WAREHOUSES:{
PortSceneHandler handler = (PortSceneHandler) SceneHandlerFactory.getSceneLoader(viewState, getBounds(), xmlLoader, resolver);
handler.displayWareStorageDialog(city, this);
break;
}
case TO_WEAPONS:{
PortSceneHandler handler = (PortSceneHandler) SceneHandlerFactory.getSceneLoader(viewState, getBounds(), xmlLoader, resolver);
handler.displayWeaponStorageDialog(city, this);
break;
}
default:
throw new IllegalArgumentException("Not implemented notice item "+noticeItem);
}
}
/**
* Check if this as a view change due to selecting something on the notice board
* @param e
* @param eventNotice
* @return
*/
private boolean isDialogChange(Event e, Object eventNotice) {
return dialog!=null && e instanceof ViewChangeEvent && eventNotice instanceof ENoticeItem;
}
/**
* Check if the event can be delegated to the scene handler.
* If there is a dialog active and the event does not concerne the closing of the dialog, the event is not propagated
* @param e
* @param eventNotice
* @return
*/
private boolean canDelegateToSceneHandler(Event e, Object eventNotice) {
return dialog==null || (e instanceof ViewChangeEvent && eventNotice == EViewChangeEvent.CLOSE_DIALOG);
}
/**
* Hanlde method for changing the main view image
* @param newScene
*/
private void handleViewChange(EScene newScene){
DisplayImageDIResolver resolver = DisplayImageDIResolver.getInstance();
ISceneHandler handler = SceneHandlerFactory.getSceneLoader(newScene, getBounds(), xmlLoader, resolver);
img = handler.getImage();
viewState = newScene;
}
/**
* {@inheritDoc}
* Replace the internal dialog with the passed dialog
*/
@Override
public void updateDialog(OpenPatricianGameDialog dialog) {
this.dialog = dialog;
}
@Override
public BufferedImage getDialogFringe() {
return loader.getImage(imageNames[1]); // fringe;
}
}