package com.iambookmaster.client.iphone.data;
import java.util.ArrayList;
import java.util.Comparator;
import com.google.code.gwt.database.client.service.Callback;
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.dom.client.Document;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Frame;
import com.iambookmaster.client.common.Base64Coder;
import com.iambookmaster.client.common.JSONParser;
import com.iambookmaster.client.locale.AppConstants;
import com.iambookmaster.client.locale.AppLocale;
import com.iambookmaster.client.model.Model;
public class IPhoneDataServiceImp extends IPhoneDataService{
private static final AppConstants appConstants = AppLocale.getAppConstants();
private static final Object[] PARAMS = new Object[0];
public Frame frame;
private Callback callback;
private boolean linkedVersionPresent;
private boolean cracked;
private boolean inAppAvailable;
private StringBuilder buffer;
public IPhoneDataServiceImp() {
init();
frame = new Frame();
frame.setVisible(false);
Document.get().getBody().appendChild(frame.getElement());
}
private native void init()/*-{
var self = this;
$wnd.iambm = function(data,full,save,inapp) {
self.@com.iambookmaster.client.iphone.data.IPhoneDataServiceImp::restore(Ljava/lang/String;ZZZ)(data,full,save,inapp);
};
$wnd.iambme = function(data,suggestion) {
self.@com.iambookmaster.client.iphone.data.IPhoneDataServiceImp::error(Ljava/lang/String;Ljava/lang/String;)(data,suggestion);
};
$wnd.iambml = function(data) {
self.@com.iambookmaster.client.iphone.data.IPhoneDataServiceImp::list(Ljava/lang/String;)(data);
};
$wnd.iambms = function(data,type) {
self.@com.iambookmaster.client.iphone.data.IPhoneDataServiceImp::single(Ljava/lang/String;I)(data,type);
};
$wnd.iambmd = function() {
self.@com.iambookmaster.client.iphone.data.IPhoneDataServiceImp::voidCallback()();
};
$wnd.iambmp = function(data,code) {
if (data) {
self.@com.iambookmaster.client.iphone.data.IPhoneDataServiceImp::price(Ljava/lang/String;)(data);
} else {
self.@com.iambookmaster.client.iphone.data.IPhoneDataServiceImp::noprice(I)(code);
}
};
}-*/;
/**
* This method is called from JavaScript
*/
private void error(String error,String suggestion){
if (callback != null) {
callback.onFailure(new DataServiceException(error));
}
}
/**
* This method is called from JavaScript
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private void price(String price){
if (callback instanceof ScalarCallback) {
ScalarCallback callback = (ScalarCallback) this.callback;
callback.onSuccess(price);
}
}
/**
* This method is called from JavaScript
*/
private void noprice(int code){
if (callback != null) {
callback.onFailure(new DataServiceException(appConstants.iphoneCannotConnectAppStore(),code,null,PARAMS));
}
}
/**
* This method is called from JavaScript
*/
private void voidCallback(){
// Window.alert("Success");
if (callback instanceof VoidCallback) {
VoidCallback callback = (VoidCallback) this.callback;
callback.onSuccess();
}
}
/**
* This method is called from JavaScript
*/
private void restore(String status,boolean full,boolean cracked,boolean inAppAvailable){
linkedVersionPresent = full;
this.cracked = cracked;
this.inAppAvailable = inAppAvailable;
if (status==null || status.length()==0) {
callback.onFailure(new DataServiceException("No state"));
} else if (callback instanceof ScalarCallback) {
@SuppressWarnings("unchecked")
ScalarCallback<String> scalarCallback = (ScalarCallback<String>) callback;
scalarCallback.onSuccess(status);
}
}
public boolean isLinkedVersionPresent() {
return linkedVersionPresent;
}
public boolean isCracked() {
return cracked;
}
public boolean isInAppAvailable() {
return inAppAvailable;
}
public void loadLastState(Model model, ScalarCallback<String> callback) {
this.callback = callback;
frame.setUrl(generateCommandURL("restore",null));
}
@Override
public void storeState(String data) {
frame.setUrl(generateCommandURL("state",data));
}
@Override
public void donate(VoidCallback callback) {
this.callback = callback;
frame.setUrl(generateCommandURL("donate",null));
}
@Override
public void calculateDonate(ScalarCallback<String> callback) {
this.callback = callback;
frame.setUrl(generateCommandURL("price",null));
}
@Override
public void cancelRequest() {
this.callback = null;
}
@Override
public void removeSplashScreen() {
callback = null;
frame.setUrl(generateCommandURL("show",null));
}
@Override
public void selectAvailableFiles(String exention, ListCallback<IPhoneFileBean> callback) {
this.callback = callback;
frame.setUrl(generateCommandURL("files",exention));
}
@Override
public void loadSingleFile(String name, ScalarCallback<String> callback) {
this.callback = callback;
this.buffer = null;
frame.setUrl(generateCommandURL("load",name));
}
/**
* This method is called from JavaScript
*/
@SuppressWarnings({ "unchecked"})
private void list(String json){
try {
if (callback instanceof ListCallback) {
ListCallback<IPhoneFileBean> callback = (ListCallback<IPhoneFileBean>) this.callback;
JSONParser parser = JSONParser.getInstance();
JavaScriptObject list = JSONParser.evalArray(json);
int l = parser.length(list);
ArrayList<IPhoneFileBean> res = new ArrayList<IPhoneFileBean>(l);
for (int i = 0; i < l; i++) {
res.add((IPhoneFileBean)parser.getRow(list, i));
}
java.util.Collections.sort(res,new Comparator<IPhoneFileBean>() {
public int compare(IPhoneFileBean o1, IPhoneFileBean o2) {
return o1.getName().compareToIgnoreCase(o2.getName());
}
});
callback.onSuccess(res);
} else if (callback != null){
callback.onFailure(new DataServiceException("Incorrect callback"));
}
} catch (Throwable e) {
sendError(e);
}
}
/**
* This method is called from JavaScript
*/
@SuppressWarnings({ "unchecked"})
private void single(String data,int type){
try {
if (callback instanceof ScalarCallback) {
ScalarCallback<String> callback = (ScalarCallback<String>) this.callback;
switch (type) {
case 1:
if (buffer==null) {
callback.onSuccess(Base64Coder.decode(data,"UTF-8"));
} else {
buffer.append(Base64Coder.decode(data,"UTF-8"));
callback.onSuccess(buffer.toString());
buffer = null;
}
break;
case 2:
if (buffer==null) {
callback.onSuccess(Base64Coder.decodeString(data));
} else {
buffer.append(Base64Coder.decodeString(data));
callback.onSuccess(buffer.toString());
buffer = null;
}
break;
case 3:
//add data to buffer
if (buffer==null) {
buffer = new StringBuilder(Base64Coder.decode(data,"UTF-8"));
} else {
buffer.append(Base64Coder.decode(data,"UTF-8"));
}
break;
case 4:
//add data to buffer
if (buffer==null) {
buffer = new StringBuilder(Base64Coder.decodeString(data));
} else {
buffer.append(Base64Coder.decodeString(data));
}
break;
default:
callback.onSuccess(data);
break;
}
} else if (callback != null){
buffer = null;
callback.onFailure(new DataServiceException("Incorrect callback"));
}
} catch (Throwable e) {
buffer = null;
sendError(e);
}
}
private void sendError(Throwable e) {
e.printStackTrace();
if (callback==null) {
Window.alert("ERROR: "+e.getMessage());
} else {
callback.onFailure(new DataServiceException("ERROR: "+e.getMessage()));
}
}
@Override
public void storeState(String state, String fileName, VoidCallback callback) {
this.callback = callback;
int i = fileName.lastIndexOf('/');
if (i>0) {
fileName = fileName.substring(i+1);
}
frame.setUrl(generateCommandURL("save",fileName+'/'+state));
}
}