package com.hokolinks.deeplinking;
import com.hokolinks.Hoko;
import com.hokolinks.deeplinking.listeners.LinkGenerationListener;
import com.hokolinks.model.Deeplink;
import com.hokolinks.model.exceptions.InvalidDomainException;
import com.hokolinks.model.exceptions.LazySmartlinkCantHaveURLsException;
import com.hokolinks.model.exceptions.LinkGenerationException;
import com.hokolinks.model.exceptions.NullDeeplinkException;
import com.hokolinks.model.exceptions.RouteNotMappedException;
import com.hokolinks.utils.log.HokoLog;
import com.hokolinks.utils.networking.async.HttpRequest;
import com.hokolinks.utils.networking.async.HttpRequestCallback;
import com.hokolinks.utils.networking.async.NetworkAsyncTask;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
/**
* LinkGenerator serves the purpose of generating Smartlinks for a given deeplink.
* It connects with the Hoko backend service and will return a http link which will redirect
* according to the correct deeplink depending on the platform it is later opened.
*/
class LinkGenerator {
private String mToken;
public LinkGenerator(String token) {
mToken = token;
}
/**
* Validates deeplinks before actually trying to generate them through a Hoko backend service
* call.
*
* @param deeplink A user generated deeplink or an annotation based deeplink.
* @param listener A LinkGenerationListener instance.
*/
public void generateSmartlink(Deeplink deeplink, LinkGenerationListener listener) {
if (deeplink == null) {
listener.onError(new NullDeeplinkException());
} else if (!Hoko.deeplinking().routing().routeExists(deeplink.getRoute())) {
listener.onError(new RouteNotMappedException());
} else {
requestForSmartlink(deeplink, listener);
}
}
/**
* Performs a request to the Hoko backend service to translate a deeplink into an Smartlink.
* Calls the listener depending on the success or failure of such a network call.
*
* @param deeplink A user generated deeplink or an annotation based deeplink.
* @param listener A LinkGenerationListener instance.
*/
private void requestForSmartlink(Deeplink deeplink,
final LinkGenerationListener listener) {
new NetworkAsyncTask(new HttpRequest(HttpRequest.HokoNetworkOperationType.POST,
"smartlinks", mToken, deeplink.json().toString())
.toRunnable(new HttpRequestCallback() {
@Override
public void onSuccess(JSONObject jsonObject) {
String smartlink = jsonObject.optString("smartlink");
if (listener != null) {
if (smartlink != null)
listener.onLinkGenerated(smartlink);
else
listener.onError(new LinkGenerationException());
}
}
@Override
public void onFailure(Exception e) {
if (listener != null)
listener.onError(new LinkGenerationException());
}
})).execute();
}
/**
* generateLazySmartlink(deeplink, domain) allows the app to generate lazy Smartlinks for the
* user to share with other users, independent of the platform, users will be redirected to the
* corresponding view. A user generated Deeplink object may be passed along to generate the
* deeplinks for all available platforms. In case the translation is possible, the method will
* return a lazy Smartlink (e.g. http://yourapp.hoko.link/lazy?uri=%2Fproduct%2F0 ).
* Where the uri query parameter will be the url encoded version of the translated deep link.
*
* @param deeplink A Deeplink object.
* @param domain The domain to which HOKO should generate a lazy Smartlink.
* (e.g. yourapp.hoko.link or yourapp.customdomain.com).
*/
String generateLazySmartlink(Deeplink deeplink, String domain) {
if (deeplink != null && domain != null) {
if (deeplink.hasURLs()) {
HokoLog.e(new LazySmartlinkCantHaveURLsException());
return null;
}
String strippedDomain = domain + "";
strippedDomain = strippedDomain.replace("http://", "");
strippedDomain = strippedDomain.replace("https://","");
if (strippedDomain.contains("/")) {
HokoLog.e(new InvalidDomainException(domain));
} else {
try {
return "http://" + domain + "lazy?uri=" + URLEncoder.encode(deeplink.getURL(), "UTF-8");
} catch (UnsupportedEncodingException e) {
HokoLog.e(e);
}
}
}
return null;
}
}