/*******************************************************************************
* Copyright (c) 2014, 2015 Scott Clarke (scott@dawg6.com).
*
* This file is part of Dawg6's Demon Hunter DPS Calculator.
*
* Dawg6's Demon Hunter DPS Calculator is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dawg6's Demon Hunter DPS Calculator is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package com.dawg6.web.dhcalc.client;
import java.util.List;
import java.util.Vector;
import com.dawg6.d3api.shared.CareerProfile;
import com.dawg6.d3api.shared.HeroProfile;
import com.dawg6.d3api.shared.ItemInformation;
import com.dawg6.d3api.shared.Leaderboard;
import com.dawg6.d3api.shared.Realm;
import com.dawg6.d3api.shared.SeasonIndex;
import com.dawg6.gwt.client.ApplicationPanel;
import com.dawg6.gwt.client.ApplicationPanel.DialogBoxResultHandler;
import com.dawg6.gwt.common.util.AsyncTask;
import com.dawg6.gwt.common.util.AsyncTaskHandler;
import com.dawg6.web.dhcalc.shared.calculator.ExportData;
import com.dawg6.web.dhcalc.shared.calculator.FormData;
import com.dawg6.web.dhcalc.shared.calculator.NewsItem;
import com.dawg6.web.dhcalc.shared.calculator.Util;
import com.dawg6.web.dhcalc.shared.calculator.Version;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.Response;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.jsonp.client.JsonpRequestBuilder;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.DialogBox;
public class Service implements DHCalcServiceAsync {
private static final Service instance = new Service();
private final DHCalcServiceAsync SERVICE = GWT.create(DHCalcService.class);
private List<NewsItem> news = new Vector<NewsItem>();
private final List<NewsHandler> newsHandlers = new Vector<NewsHandler>();
private Timer newsTimer;
private Service() {
newsTimer = new Timer(){
@Override
public void run() {
checkNews(null);
}};
checkNews(null);
newsTimer.scheduleRepeating(30000);
}
public static Service getInstance() {
return instance;
}
public void addNewsHandler(NewsHandler handler) {
if (!newsHandlers.contains(handler)) {
newsHandlers.add(handler);
if (!news.isEmpty())
handler.newsChanged(news);
}
}
public void removeNewsHandler(NewsHandler handler) {
newsHandlers.remove(handler);
}
public interface NewsHandler {
void newsChanged(List<NewsItem> news);
}
public void execute(final AsyncTask task) {
execute(true, task);
}
private AsyncTaskHandler waitDialog = null;
public void execute(boolean showDialog, final AsyncTask task) {
boolean createDlg = false;
if ((waitDialog == null) && showDialog) {
waitDialog = ApplicationPanel.showWaitDialogBox(
"Please wait...", null);
createDlg = true;
}
final AsyncTaskHandler handler = createDlg ? new AsyncTaskHandler(){
@Override
public void taskCompleted() {
waitDialog.taskCompleted();
waitDialog = null;
}} : AsyncTaskHandler.Default;
checkVersion(new Handler<VersionCheck>() {
@Override
public void handleResult(VersionCheck result) {
if (result.success) {
task.run(handler);
} else {
handler.taskCompleted();
}
}
});
}
public void checkVersion(final Handler<VersionCheck> handler) {
versionCheck(new Handler<VersionCheck>() {
@Override
public void handleResult(VersionCheck result) {
if (!result.success) {
versionCheckFailed(result);
}
if (handler != null)
handler.handleResult(result);
}
});
}
private DialogBox reloadDialogBox = null;
private void versionCheckFailed(VersionCheck result) {
if (newsTimer != null) {
newsTimer.cancel();
newsTimer = null;
}
if (reloadDialogBox == null) {
final DialogBoxResultHandler dialogHandler = new DialogBoxResultHandler() {
@Override
public void dialogBoxResult(int result) {
reloadDialogBox = null;
if (result == ApplicationPanel.OK)
forceReload();
}
};
String message;
String title;
if (result.serverVersion != null) {
title = "Server Version Mismatch";
message = "New Version (" + result.serverVersion
+ ") available on Server.";
} else if (result.exception != null) {
title = "Error";
message = result.exception;
} else {
title = "Error";
message = "Unknown error communicating with server.";
}
message += "\nPress OK to force browser refresh.";
reloadDialogBox = ApplicationPanel.showDialogBox(title, message,
ApplicationPanel.OK | ApplicationPanel.CANCEL,
dialogHandler);
} else {
reloadDialogBox.center();
reloadDialogBox.hide();
reloadDialogBox.show();
}
}
public void checkNews(final AsyncTaskHandler handler) {
this.getNews(new AsyncCallback<NewsItem[]>(){
@Override
public void onFailure(Throwable caught) {
GWT.log("Unable to retrieve News");
handler.taskCompleted();
}
@Override
public void onSuccess(NewsItem[] result) {
List<NewsItem> news = Util.arrayToList(result);
setNews(news);
if (handler != null)
handler.taskCompleted();
}});
}
protected void setNews(List<NewsItem> news) {
if (!this.news.equals(news)) {
this.news = news;
for (NewsHandler h : this.newsHandlers) {
h.newsChanged(news);
}
}
}
@Override
public void getProfile(final Realm realm, final String profile,
final int tag, final AsyncCallback<CareerProfile> callback) {
execute(new AsyncTask() {
@Override
public void run(final AsyncTaskHandler handler) {
SERVICE.getProfile(realm, profile, tag,
new DelegateCallback<CareerProfile>(handler, callback));
}
});
}
@Override
public void getItem(final Realm realm, final String item,
final AsyncCallback<ItemInformation> callback) {
execute(new AsyncTask() {
@Override
public void run(final AsyncTaskHandler handler) {
SERVICE.getItem(
realm,
item,
new DelegateCallback<ItemInformation>(handler, callback));
}
});
}
@Override
public void getHero(final Realm realm, final String profile, final int tag,
final int id, final AsyncCallback<HeroProfile> callback) {
execute(new AsyncTask() {
@Override
public void run(AsyncTaskHandler handler) {
SERVICE.getHero(realm, profile, tag, id,
new DelegateCallback<HeroProfile>(handler, callback));
}
});
}
// @Override
// public void serializeFormData(final FormData data,
// final AsyncCallback<String> callback) {
// execute(new AsyncTask() {
//
// @Override
// public void run(AsyncTaskHandler handler) {
// SERVICE.serializeFormData(data, new DelegateCallback<String>(
// handler, callback));
// }
// });
//
// }
@Override
public void getClientData(final String client,
final AsyncCallback<FormData> callback) {
execute(new AsyncTask() {
@Override
public void run(AsyncTaskHandler handler) {
SERVICE.getClientData(client, new DelegateCallback<FormData>(
handler, callback));
}
});
}
@Override
public void exportData(final ExportData data,
final AsyncCallback<String> callback) {
execute(new AsyncTask() {
@Override
public void run(AsyncTaskHandler handler) {
SERVICE.exportData(data, new DelegateCallback<String>(handler,
callback));
}
});
}
@Override
public void getVersion(final AsyncCallback<Version> callback) {
execute(new AsyncTask() {
@Override
public void run(AsyncTaskHandler handler) {
SERVICE.getVersion(new DelegateCallback<Version>(handler,
callback));
}
});
}
// @Override
// public void toJson(final JsonObject object,
// final AsyncCallback<String> callback) {
// execute(new AsyncTask() {
//
// @Override
// public void run(AsyncTaskHandler handler) {
// SERVICE.toJson(object, new DelegateCallback<String>(handler,
// callback));
// }
// });
// }
//
// @Override
// public void fromJson(final String json, final String shooter,
// final AsyncCallback<JsonObject> callback) {
// execute(new AsyncTask() {
//
// @Override
// public void run(AsyncTaskHandler handler) {
// SERVICE.fromJson(json, shooter, new DelegateCallback<JsonObject>(
// handler, callback));
// }
// });
// }
private static class VersionCheck {
public boolean success;
public String serverVersion;
public String exception;
}
private interface Handler<T> {
void handleResult(T result);
}
public void httpRequest(String url, final AsyncCallback<String> handler) {
try {
JsonpRequestBuilder builder = new JsonpRequestBuilder();
builder.requestObject(url, new AsyncCallback<JavaScriptObject>() {
@Override
public void onFailure(Throwable caught) {
handler.onFailure(caught);
}
@Override
public void onSuccess(JavaScriptObject result) {
JSONObject json = new JSONObject(result);
handler.onSuccess(json.toString());
}
});
} catch (RuntimeException e) {
handler.onFailure(e);
} catch (Exception e) {
handler.onFailure(e);
}
}
public void versionCheck(final Handler<VersionCheck> handler) {
Scheduler.get().scheduleDeferred(new Command() {
@Override
public void execute() {
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET,
GWT.getHostPageBaseURL() + "version?v2");
final VersionCheck result = new VersionCheck();
try {
builder.sendRequest(null, new RequestCallback() {
@Override
public void onResponseReceived(Request request,
Response response) {
String text = response.getText();
if (text != null) {
if (text.startsWith(Version.PREFIX)) {
result.serverVersion = text
.substring(Version.PREFIX.length());
if (text.startsWith(Version.getVersion()
.getPrefixString())) {
result.success = true;
}
}
}
if ((!result.success)
&& (result.serverVersion == null)) {
result.exception = "Unable to obtain Server version.";
}
if (handler != null)
handler.handleResult(result);
}
@Override
public void onError(Request request, Throwable exception) {
result.success = false;
result.exception = "Error communicating with server.";
if (handler != null)
handler.handleResult(result);
}
});
} catch (Exception e) {
result.success = false;
result.exception = "Error communicating with server.";
if (handler != null)
handler.handleResult(result);
}
}
});
}
public static native void forceReload() /*-{
$wnd.location.reload(true);
}-*/;
// @Override
// public void logData(final CharacterData data,
// final AsyncCallback<Void> callback) {
// execute(new AsyncTask() {
//
// @Override
// public void run(AsyncTaskHandler handler) {
// SERVICE.logData(data, new DelegateCallback<Void>(handler,
// callback));
// }
// });
// }
//
// @Override
// public void getStats(final Rune sentryRune, final ActiveSkill[] skills,
// final Rune[] runes, final AsyncCallback<DBStatistics> callback) {
// execute(new AsyncTask() {
//
// @Override
// public void run(AsyncTaskHandler handler) {
// SERVICE.getStats(sentryRune, skills, runes,
// new DelegateCallback<DBStatistics>(handler, callback));
// }
// });
// }
@Override
public void getSeasonEraIndex(final Realm realm, final AsyncCallback<SeasonIndex> callback) {
execute(new AsyncTask() {
@Override
public void run(AsyncTaskHandler handler) {
SERVICE.getSeasonEraIndex(realm, new DelegateCallback<SeasonIndex>(
handler, callback));
}
});
}
@Override
public void getLeaderboard(final Realm realm, final int seasonEra, final boolean isEra,
final String which, final AsyncCallback<Leaderboard> callback) {
execute(new AsyncTask() {
@Override
public void run(AsyncTaskHandler handler) {
SERVICE.getLeaderboard(realm, seasonEra, isEra, which, new DelegateCallback<Leaderboard>(
handler, callback));
}
});
}
@Override
public void getNews(final AsyncCallback<NewsItem[]> callback) {
execute(false, new AsyncTask() {
@Override
public void run(AsyncTaskHandler handler) {
SERVICE.getNews(new DelegateCallback<NewsItem[]>(
handler, callback));
}
});
}
}