/*
* Copyright 2015, Tanmay Parikh
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.tanmay.blip.networking;
import android.app.IntentService;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
import com.crashlytics.android.Crashlytics;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import com.tanmay.blip.BlipApplication;
import com.tanmay.blip.database.DatabaseManager;
import com.tanmay.blip.database.SharedPrefs;
import com.tanmay.blip.models.Comic;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class XKCDDownloader extends IntentService {
public static final String LATEST_URL = "http://xkcd.com/info.0.json";
public static final String COMICS_URL = "http://xkcd.com/%d/info.0.json";
public static final String DOWNLOAD_PROGRESS = "com.tanmay.blip.DOWNLOAD_PROGRESS";
public static final String DOWNLOAD_SUCCESS = "com.tanmay.blip.DOWNLOAD_SUCCESS";
public static final String DOWNLOAD_FAIL = "com.tanmay.blip.DOWNLOAD_FAIL";
public static final String DOWNLOAD_TODAY = "com.tanmay.blip.DOWNLOAD_TODAY";
public static final String DOWNLOAD_ALL = "com.tanmay.blip.DOWNLOAD_ALL";
public static final String DOWNLOAD_SPECIFIC = "com.tanmay.blip.DOWNLOAD_SPECIFIC";
public static final String DOWNLOAD_TRANSCRIPT = "com.tanmay.blip.DOWNLOAD_TRANSCRIPT";
public static final String DOWNLOAD_LAST_TEN = "com.tanmay.blip.DOWNLOAD_LAST_TEN";
public static final String COMIC_NUM = "comicNum";
public static final String PROGRESS = "progress";
public static final String TITLE = "title";
public XKCDDownloader() {
super("XKCDDownloaderService");
}
public XKCDDownloader(String name) {
super(name);
}
@Override
protected void onHandleIntent(Intent intent) {
switch (intent.getAction()) {
case DOWNLOAD_TODAY:
downloadToday();
break;
case DOWNLOAD_ALL:
downloadAll();
break;
case DOWNLOAD_SPECIFIC:
downloadSpecific(intent.getExtras().getInt(COMIC_NUM));
break;
case DOWNLOAD_TRANSCRIPT:
downloadAllMissingTranscripts();
break;
case DOWNLOAD_LAST_TEN:
redownloadLastTen();
}
}
private void downloadSpecific(int i) {
Gson gson = new Gson();
DatabaseManager databaseManager = new DatabaseManager(this);
String url = String.format(COMICS_URL, i);
Request request = new Request.Builder().url(url).build();
try {
Response response = BlipApplication.getInstance().client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException();
Comic comic = gson.fromJson(response.body().string(), Comic.class);
databaseManager.addComic(comic);
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(DOWNLOAD_SUCCESS));
} catch (IOException e) {
e.printStackTrace();
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(DOWNLOAD_FAIL));
}
}
private void downloadToday() {
DatabaseManager databaseManager = new DatabaseManager(this);
Gson gson = new Gson();
Request request = new Request.Builder().url(LATEST_URL).build();
try {
Response response = BlipApplication.getInstance().client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException();
Comic comic = gson.fromJson(response.body().string(), Comic.class);
if (!databaseManager.comicExists(comic))
databaseManager.addComic(comic);
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(DOWNLOAD_SUCCESS));
} catch (IOException e) {
e.printStackTrace();
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(DOWNLOAD_FAIL));
}
}
private void redownloadLastTen() {
final Gson gson = new Gson();
final DatabaseManager databaseManager = new DatabaseManager(this);
try {
Request todayReq = new Request.Builder().url(LATEST_URL).build();
Response response = BlipApplication.getInstance().client.newCall(todayReq).execute();
if (!response.isSuccessful()) throw new IOException();
Comic comic = gson.fromJson(response.body().string(), Comic.class);
final CountDownLatch latch = new CountDownLatch(10);
final Executor executor = Executors.newFixedThreadPool(5);
int num = comic.getNum();
for (int i = num - 9; i <= num; i++) {
final int index = i;
executor.execute(new Runnable() {
@Override
public void run() {
try {
String url = String.format(COMICS_URL, index);
Request request = new Request.Builder().url(url).build();
Response response = BlipApplication.getInstance().client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException();
String responseBody = response.body().string();
Comic comic = null;
try {
comic = gson.fromJson(responseBody, Comic.class);
} catch (JsonSyntaxException e) {
Crashlytics.log(1, "XKCDDownloader", e.getMessage() + " POS:" + index);
}
if (comic != null) {
if (databaseManager.comicExists(comic)) {
databaseManager.updateComic(comic);
} else {
databaseManager.addComic(comic);
}
}
} catch (IOException e) {
e.printStackTrace();
LocalBroadcastManager.getInstance(XKCDDownloader.this).sendBroadcast(new Intent(DOWNLOAD_FAIL));
} finally {
latch.countDown();
}
}
});
}
try {
latch.await();
} catch (InterruptedException e) {
LocalBroadcastManager.getInstance(XKCDDownloader.this).sendBroadcast(new Intent(DOWNLOAD_FAIL));
}
SharedPrefs.getInstance().setLastRedownladTime(System.currentTimeMillis());
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(DOWNLOAD_SUCCESS));
} catch (IOException e) {
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(DOWNLOAD_FAIL));
}
}
private void downloadAllMissingTranscripts() {
final Gson gson = new Gson();
final DatabaseManager databaseManager = new DatabaseManager(this);
List<Integer> nums = databaseManager.getAllMissingTranscripts();
if (nums.size() > 1) {
final CountDownLatch latch = new CountDownLatch(nums.size());
final Executor executor = Executors.newFixedThreadPool(nums.size() / 2);
for (int i : nums) {
final int index = i;
executor.execute(new Runnable() {
@Override
public void run() {
try {
String url = String.format(COMICS_URL, index);
Request request = new Request.Builder().url(url).build();
Response response = BlipApplication.getInstance().client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException();
String responseBody = response.body().string();
Comic comic = null;
try {
comic = gson.fromJson(responseBody, Comic.class);
} catch (JsonSyntaxException e) {
Crashlytics.log(1, "XKCDDownloader", e.getMessage() + " POS:" + index);
}
if (comic != null) {
databaseManager.updateComic(comic);
}
} catch (IOException e) {
e.printStackTrace();
LocalBroadcastManager.getInstance(XKCDDownloader.this).sendBroadcast(new Intent(DOWNLOAD_FAIL));
} finally {
latch.countDown();
}
}
});
}
try {
latch.await();
} catch (InterruptedException e) {
LocalBroadcastManager.getInstance(XKCDDownloader.this).sendBroadcast(new Intent(DOWNLOAD_FAIL));
}
SharedPrefs.getInstance().setLastTranscriptCheckTime(System.currentTimeMillis());
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(DOWNLOAD_SUCCESS));
} else {
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(DOWNLOAD_SUCCESS));
}
}
private void downloadAll() {
final Gson gson = new Gson();
final DatabaseManager databaseManager = new DatabaseManager(this);
Request request = new Request.Builder().url(LATEST_URL).build();
try {
final Response response = BlipApplication.getInstance().client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException();
Comic comic = gson.fromJson(response.body().string(), Comic.class);
final int num = comic.getNum();
final CountDownLatch latch = new CountDownLatch(num);
final Executor executor = Executors.newFixedThreadPool(10);
for (int i = 1; i <= num; i++) {
final int index = i;
executor.execute(new Runnable() {
@Override
public void run() {
try {
if (index != 404) {
String url = String.format(COMICS_URL, index);
Request newReq = new Request.Builder().url(url).build();
Response newResp = BlipApplication.getInstance().client.newCall(newReq).execute();
if (!newResp.isSuccessful()) throw new IOException();
String resp = newResp.body().string();
Comic comic1 = null;
try {
comic1 = gson.fromJson(resp, Comic.class);
} catch (JsonSyntaxException e) {
Crashlytics.log(1, "XKCDDownloader", e.getMessage() + " POS:" + index);
}
if (comic1 != null) {
databaseManager.addComic(comic1);
double progress = ((double) databaseManager.getCount() / num) * 100;
Intent intent = new Intent(DOWNLOAD_PROGRESS);
intent.putExtra(PROGRESS, progress);
intent.putExtra(TITLE, comic1.getTitle());
LocalBroadcastManager.getInstance(XKCDDownloader.this).sendBroadcast(intent);
}
}
} catch (IOException e) {
e.printStackTrace();
LocalBroadcastManager.getInstance(XKCDDownloader.this).sendBroadcast(new Intent(DOWNLOAD_FAIL));
} finally {
latch.countDown();
}
}
});
}
try {
latch.await();
} catch (InterruptedException e) {
throw new IOException(e);
}
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(DOWNLOAD_SUCCESS));
} catch (IOException e) {
e.printStackTrace();
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(DOWNLOAD_FAIL));
}
}
}