package com.iambookmaster.client.iphone.urq;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import com.google.code.gwt.database.client.service.DataServiceException;
import com.google.code.gwt.database.client.service.ListCallback;
import com.google.code.gwt.database.client.service.ScalarCallback;
import com.google.code.gwt.database.client.service.VoidCallback;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.iambookmaster.client.common.Base64Coder;
import com.iambookmaster.client.common.JSONBuilder;
import com.iambookmaster.client.common.JSONParser;
import com.iambookmaster.client.iphone.IPhoneCanvas;
import com.iambookmaster.client.iphone.IPhoneViewListenerAdapter;
import com.iambookmaster.client.iphone.common.IPhoneButton;
import com.iambookmaster.client.iphone.common.IPhoneFlatButton;
import com.iambookmaster.client.iphone.data.IPhoneDataService;
import com.iambookmaster.client.iphone.data.IPhoneFileBean;
import com.iambookmaster.client.iphone.images.IPhoneImages;
import com.iambookmaster.client.iphone.images.IPhoneStyles;
import com.iambookmaster.client.iurq.Core;
import com.iambookmaster.client.iurq.URQParser;
import com.iambookmaster.client.iurq.URQUI;
import com.iambookmaster.client.iurq.logic.Btn;
import com.iambookmaster.client.iurq.logic.InvVar;
import com.iambookmaster.client.iurq.logic.InvVar.Action;
import com.iambookmaster.client.iurq.logic.Pause;
import com.iambookmaster.client.iurq.logic.Play;
import com.iambookmaster.client.iurq.logic.URQImage;
public class IPhoneURQPlayer extends IPhoneViewListenerAdapter{
static final IPhoneStyles css = IPhoneImages.INSTANCE.css();
private static final String FIELD_GAME_STATE = "a";
private static final String FIELD_TEXT = "b";
private static final String FIELD_GAME_TEXT = "c";
private static final String FIELD_LOCATION = "d";
private static final String FIELD_GAME_BUTTONS = "e";
private static final String FIELD_GAME_NAME = "f";
private static final String FIELD_GAME_ANYKEY = "i";
private Core core;
private IPhoneCanvas canvas;
private ArrayList<Btn> buttons = new ArrayList<Btn>();
private ArrayList<String> texts = new ArrayList<String>();
private IPhoneURQPlayerListenr listener;
private ClickHandler gameOverHander;
private IPhoneURQInventory inventory;
private boolean redrawn;
private IPhoneURQInventoryListener inventoryListenr;
private IPhoneURQActions inventotyActions;
private IPhoneDataService dataService;
private String fileName;
private int nextFileCounter;
private boolean anykeyState;
private Timer pauseTimer;
private int timerCounter;
protected boolean pauseSuspended;
private boolean stateSaved;
public IPhoneURQPlayer(IPhoneDataService dataService,IPhoneURQPlayerListenr lst) {
this.listener = lst;
this.dataService = dataService;
gameOverHander = new ClickHandler() {
public void onClick(ClickEvent event) {
cancelPause();
listener.exit();
}
};
inventoryListenr = new IPhoneURQInventoryListener() {
public void useInventory(String name, InvVar var) {
use(name);
}
public void useInventory() {
use(core.getInventoryName());
}
private void use(String itemName) {
nextAction();
Vector<Action> actions = core.listOfInventActions(itemName);
redrawn = false;
if (actions == null || actions.size()==0) {
//nothing
} else if (actions.size()==1) {
//single action - use now
core.doAction(actions.get(0));
} else {
//show list of actions
inventotyActions.show(canvas, core, itemName, actions);
return;
}
processCommand();
if (redrawn==false) {
_redraw(canvas,1);
}
}
public void forward() {
}
public void back() {
_redraw(canvas,-1);
}
public void doAction(Action action) {
nextAction();
redrawn = false;
core.doAction(action);
core.tick();
if (redrawn==false) {
_redraw(canvas,1);
}
}
};
inventory = new IPhoneURQInventory(inventoryListenr);
inventotyActions = new IPhoneURQActions(inventoryListenr);
init();
}
public void init() {
core = new Core("Инвентарь");
core.init(new URQUI() {
private StringBuilder builder=new StringBuilder();
private boolean ignoreEmptyLine=true;
public void resizeItems() {
}
public void print(String s, int color) {
int i = s.indexOf('\n');
if (i<0) {
builder.append(s);
ignoreEmptyLine = false;
} else if (i==0) {
//at the beginning
if (ignoreEmptyLine) {
if (s.length()==1) {
//empty line
return;
} else {
s = s.substring(1);
}
}
texts.add(builder.toString());
builder.setLength(0);
if (s.length()==1) {
ignoreEmptyLine = true;
return;
} else {
builder.append(s.substring(1));
}
} else if (i==s.length()-1) {
//at the end
builder.append(s.substring(0,i));
texts.add(builder.toString());
builder.setLength(0);
} else {
//in the middle
builder.append(s.substring(0,i));
texts.add(builder.toString());
builder.setLength(0);
print(s.substring(i+1),color);
}
ignoreEmptyLine = false;
}
public void invRefresh() {
}
public String getInput() {
return null;
}
public void enableInput() {
}
public void doExit() {
listener.exit();
}
public void disableInput() {
}
public void clear() {
anykeyState = false;
builder.setLength(0);
ignoreEmptyLine = true;
buttons.clear();
texts.clear();
}
public void addButton(Btn btn) {
buttons.add(btn);
}
public void end() {
flushBuffer();
if (canvas != null) {
_redraw(canvas,1);
if (stateSaved==false) {
//no "save" command was performed
dataService.storeState(storeGameState(null));
}
}
}
private void flushBuffer() {
if (builder.length()>0) {
texts.add(builder.toString());
builder.setLength(0);
}
ignoreEmptyLine = true;
}
public String loadFile(String s) {
return null;
}
public void play(Play operator) {
}
public void anykey() {
anykeyState=true;
end();
}
public void save(String location) {
flushBuffer();
saveState(location);
}
public void showImage(URQImage image) {
// TODO Auto-generated method stub
}
public void pause(Pause pause) {
startPause((int)pause.getTime()/100);
end();
}
});
}
private void startPause(int time) {
if (time > 0 && pauseTimer==null) {
pauseTimer = new Timer() {
@Override
public void run() {
if (pauseSuspended) {
return;
}
if (timerCounter>0) {
timerCounter--;
if (timerCounter==0) {
//last tick
cancelPause();
stateSaved=false;
core.tick();
}
} else {
//release timer
cancelPause();
}
}
};
pauseTimer.scheduleRepeating(100);
}
timerCounter = time;
}
private void cancelPause() {
timerCounter = 0;
if (pauseTimer!=null) {
pauseTimer.cancel();
pauseTimer = null;
}
pauseSuspended = false;
}
public String getLastQuestName(String json) {
try {
return JSONParser.getInstance().propertyString(JSONParser.eval(Base64Coder.decodeString(json)), FIELD_GAME_NAME);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public void restoreState(String json, boolean fromSave) {
JavaScriptObject obj = JSONParser.eval(Base64Coder.decodeString(json));
JSONParser parser = JSONParser.getInstance();
String state = parser.propertyString(obj, FIELD_GAME_STATE);
core.load(new URQParser(), state);
stateSaved=true;
core.tick();
if (fromSave==false) {
texts.clear();
buttons.clear();
Object data = parser.property(obj, FIELD_GAME_TEXT);
if (data != null) {
//restore content of the screen
int len = parser.length(data);
for (int i = 0; i < len; i++) {
Object row = parser.getRow(data, i);
String text = parser.propertyString(row, FIELD_TEXT);
texts.add(text);
}
}
data = parser.property(obj, FIELD_GAME_BUTTONS);
if (data != null) {
//restore active buttons
int len = parser.length(data);
StringBuilder builder = new StringBuilder("btn ");
for (int i = 0; i < len; i++) {
Object row = parser.getRow(data, i);
String text = parser.propertyString(row, FIELD_TEXT);
String location = parser.propertyString(row, FIELD_LOCATION);
builder.setLength(4);
builder.append(location);
builder.append(',');
builder.append(text);
Btn btn = new Btn(core, builder.toString());
buttons.add(btn);
}
}
}
}
private String storeGameState(String location) {
JSONBuilder builder = JSONBuilder.getStartInstance();
builder.newRow();
builder.field(FIELD_GAME_STATE, core.save(location));
builder.field(FIELD_GAME_NAME, fileName);
builder.field(FIELD_GAME_ANYKEY, anykeyState);
if (texts.isEmpty()==false) {
JSONBuilder jsonBuilder = builder.getInstance();
for (String text : texts) {
jsonBuilder.newRow();
jsonBuilder.field(FIELD_TEXT, text);
}
builder.childArray(FIELD_GAME_TEXT,jsonBuilder);
}
if (buttons.isEmpty()==false) {
JSONBuilder jsonBuilder = builder.getInstance();
for (Btn btn : buttons) {
jsonBuilder.newRow();
jsonBuilder.field(FIELD_TEXT, btn.getName());
jsonBuilder.field(FIELD_LOCATION, btn.getLocation());
}
builder.childArray(FIELD_GAME_BUTTONS,jsonBuilder);
}
return Base64Coder.encodeString(builder.toString());
}
private void saveState(String location) {
stateSaved=true;
String nextFileName;
if (nextFileCounter>0) {
nextFileName = "_"+nextFileCounter+".sav";
} else {
nextFileName = ".sav";
}
int i = fileName.lastIndexOf('.');
if (i>0) {
nextFileName = fileName.substring(0,i)+nextFileName;
} else {
nextFileName = fileName+nextFileName;
}
i = fileName.lastIndexOf('/');
if (i<0) {
i = fileName.lastIndexOf('\\');
}
final String name = i>0 ? nextFileName.substring(i+1) : nextFileName;
dataService.storeState(storeGameState(location),nextFileName,new VoidCallback() {
public void onFailure(DataServiceException error) {
Window.alert("Ошибка сохранения "+error.getMessage());
}
public void onSuccess() {
nextFileCounter++;
Window.alert("Игра сохранена в "+name);
}
});
}
public void play(String quest, IPhoneCanvas cvs,final boolean runNow, final String fileName, final Command executeWhenReady) {
// Window.alert("Len="+quest.length());
cancelPause();
nextFileCounter = 0;
this.canvas = cvs;
this.fileName = fileName;
init();
stateSaved = true;
new URQParser().startParse(quest, core);
if (executeWhenReady != null) {
executeWhenReady.execute();
} else if (cvs != null) {
runLoadedGame();
}
}
private void runLoadedGame() {
dataService.selectAvailableFiles("sav", new ListCallback<IPhoneFileBean>() {
public void onFailure(DataServiceException error) {
//no saved games
processCommand();
}
public void onSuccess(List<IPhoneFileBean> result) {
int i = fileName.lastIndexOf('.');
if (i<=0 || result.size()==0) {
//no save files
processCommand();
return;
}
ArrayList<IPhoneFileBean> saves = new ArrayList<IPhoneFileBean>();
String prefix = fileName.substring(0,i);
for (IPhoneFileBean fileBean : result) {
if (fileBean.getPath().startsWith(prefix)) {
//our save
saves.add(fileBean);
}
}
if (saves.size()>0) {
String last = saves.get(saves.size()-1).getPath();
last = last.substring(prefix.length());
i = last.lastIndexOf('.');
if (i>0) {
last = last.substring(0,i);
}
if (last.length()>0 && last.charAt(0)=='_') {
try {
nextFileCounter=Integer.parseInt(last.substring(1))+1;
} catch (NumberFormatException e) {
nextFileCounter=1;
}
} else {
nextFileCounter=1;
}
//select saved game
IPhoneURQSelectFile selectFile = new IPhoneURQSelectFile("Выбрать сохраненную игру","Новая игра") {
public void forward() {
//start from new game
processCommand();
}
public void back() {
listener.exit();
}
@Override
protected void selectFile(IPhoneFileBean file) {
//restore saved game
dataService.loadSingleFile(file.getPath(), new ScalarCallback<String>() {
public void onFailure(DataServiceException error) {
//failed - start from new game
processCommand();
}
public void onSuccess(String result) {
try {
restoreState(result,true);
//IPhoneURQPlayer.this.show(canvas);
} catch (Exception e) {
e.printStackTrace();
core.reset();
processCommand();
}
}
});
}
@Override
protected void newFile() {
//start from new game
processCommand();
}
};
selectFile.show(canvas, saves);
} else {
//no saved games
processCommand();
}
}
});
}
private void processCommand() {
//perform initial steps
stateSaved=false;
core.tick();
//redraw screen
// show(canvas);
}
public void show(IPhoneCanvas canvas) {
this.canvas = canvas;
_redraw(canvas,1);
}
public void redraw(IPhoneCanvas canvas) {
_redraw(canvas, 0);
}
public void _redraw(IPhoneCanvas canvas,int animation) {
if (pauseSuspended) {
pauseSuspended = false;
}
canvas.setListener(IPhoneURQPlayer.this);
switch (animation) {
case -1:
canvas.clearWithAnimation(true);
break;
case 1:
canvas.clearWithAnimation(false);
break;
default:
canvas.clear();
break;
}
for (String text : texts) {
if (text.length()>0) {
canvas.add(new Label(text));
} else {
canvas.add(new HTML(" "));
}
}
if (anykeyState) {
//wait for any click
} else if (buttons.size()==0 && pauseTimer==null) {
//no buttons, no pause - end of the game
IPhoneButton button = new IPhoneButton("Конец");
canvas.add(button);
canvas.addClickHandler(button, gameOverHander);
} else {
//some actions available
for (Btn btn : buttons) {
ClickHandler handler = new ClickHandlerBtn(btn);
IPhoneFlatButton button = new IPhoneFlatButton(btn.getName());
canvas.add(button);
canvas.addClickHandler(button, handler);
}
}
canvas.done();
}
@Override
public void click(int x, int y) {
if (anykeyState) {
//user clicked to screen
nextAction();
core.tick();
}
}
private void nextAction() {
stateSaved=false;
anykeyState = false;
cancelPause();
}
public void back() {
pauseSuspended = true;
listener.rootMenu();
}
public void forward() {
//switch to Inventory
inventory.show(canvas,core);
}
public void drawn() {
redrawn=true;
}
public class ClickHandlerBtn implements ClickHandler {
private Btn btn;
public ClickHandlerBtn(Btn btn) {
this.btn = btn;
}
public void onClick(ClickEvent event) {
nextAction();
buttons.clear();
core.doButton(btn);
core.tick();
}
}
}