package com.dotcool.reader.service;

import java.util.ArrayList;
import java.util.Date;

import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Binder;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;

import com.dotcool.reader.Constants;
import com.dotcool.reader.LNReaderApplication;
import com.dotcool.reader.callback.CallbackEventData;
import com.dotcool.reader.callback.ICallbackNotifier;
import com.dotcool.reader.dao.NovelsDao;
import com.dotcool.reader.model.PageModel;
import com.dotcool.reader.model.UpdateInfoModel;
import com.dotcool.reader.model.UpdateType;
import com.dotcool.view.MainTabActivity;

public class UpdateService extends Service {
	private final IBinder mBinder = new MyBinder();
	public boolean force = false;
	public final static String TAG = UpdateService.class.toString();
	private static boolean isRunning;
	public ICallbackNotifier notifier;

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.d(TAG, "onStartCommand");
		execute();
		return Service.START_NOT_STICKY;
	}

	@Override
	public IBinder onBind(Intent arg0) {
		Log.d(TAG, "onBind");
		return mBinder;
	}

	@Override
	public void onCreate() {
		// Display a notification about us starting. We put an icon in the status bar.
		Log.d(TAG, "onCreate");
		execute();
	}

	@TargetApi(11)
	public void execute() {
		if (!shouldRun(force)) {
			// Reschedule for next run
			MyScheduleReceiver.reschedule(this);
			isRunning = false;
			return;
		}

		if (!isRunning) {
			SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
			SharedPreferences.Editor editor = sharedPrefs.edit();
			editor.putString(Constants.PREF_RUN_UPDATES, "Running...");
			editor.putString(Constants.PREF_RUN_UPDATES_STATUS, "");
			editor.commit();

//			GetUpdatedChaptersTask task = new GetUpdatedChaptersTask(this, GetAutoDownloadUpdatedChapterPreferences(), notifier);
//			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
//				task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
//			else
//				task.execute();

			// add on Download List
			LNReaderApplication.getInstance().addDownload(TAG, "Update Service");
		}
	}

	private boolean GetAutoDownloadUpdatedChapterPreferences() {
		return PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREF_AUTO_DOWNLOAD_UPDATED_CHAPTER, false);
	}

	public class MyBinder extends Binder {
		public UpdateService getService() {
			Log.d(TAG, "getService");
			return UpdateService.this;
		}
	}

	public void sendNotification(ArrayList<PageModel> updatedChapters) {
		NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

		if (updatedChapters != null && updatedChapters.size() > 0) {
			Log.d(TAG, "sendNotification");

			// remove previous update history.
			// NovelsDao.getInstance(this).deleteAllUpdateHistory();

			// create UpdateInfoModel list
			int updateCount = 0;
			int newCount = 0;
			int newNovel = 0;
			ArrayList<UpdateInfoModel> updatesInfo = new ArrayList<UpdateInfoModel>();
			for (PageModel pageModel : updatedChapters) {
				UpdateInfoModel updateInfo = new UpdateInfoModel();

				if (pageModel.getType().equalsIgnoreCase(PageModel.TYPE_NOVEL)) {
					++newNovel;
					updateInfo.setUpdateTitle("New Novel: " + pageModel.getTitle());
					updateInfo.setUpdateType(UpdateType.NewNovel);
				} else if (pageModel.getType().equalsIgnoreCase(PageModel.TYPE_TOS)) {
					updateInfo.setUpdateTitle("Updated TOS");
					updateInfo.setUpdateType(UpdateType.UpdateTos);
				} else {
					if (pageModel.isUpdated()) {
						updateInfo.setUpdateType(UpdateType.Updated);
						++updateCount;
					} else {
						updateInfo.setUpdateType(UpdateType.New);
						++newCount;
					}

					String novelTitle = "";
					try {
						novelTitle = pageModel.getBook().getParent().getPageModel().getTitle() + ": ";
					} catch (Exception ex) {
						Log.e(TAG, "Error when getting Novel title", ex);
					}

					updateInfo.setUpdateTitle(novelTitle + pageModel.getTitle() + " (" + pageModel.getBook().getTitle() + ")");
				}

				updateInfo.setUpdateDate(pageModel.getLastUpdate());
				updateInfo.setUpdatePage(pageModel.getPage());
				updateInfo.setUpdatePageModel(pageModel);

				// insert to db
				NovelsDao.getInstance(this).insertUpdateHistory(updateInfo);
				updatesInfo.add(updateInfo);
			}

			if (getConsolidateNotificationPref()) {
				createConsolidatedNotification(mNotificationManager, updateCount, newCount, newNovel);
			} else {
				int id = Constants.NOTIFIER_ID;
				boolean first = true;
				for (UpdateInfoModel updateInfoModel : updatesInfo) {
					final int notifId = ++id;
					Log.d(TAG, "set Notification for: " + updateInfoModel.getUpdatePage());
					Notification notification = getNotificationTemplate(first);
					first = false;

					prepareNotification(notifId, updateInfoModel, notification);
					mNotificationManager.notify(notifId, notification);
				}
			}
		}

		updateStatus("OK");
		Toast.makeText(this, "Update Service completed", Toast.LENGTH_SHORT).show();
		LNReaderApplication.getInstance().updateDownload(TAG, 100, "Update Service completed");

		// remove from download list
		LNReaderApplication.getInstance().removeDownload(TAG);
	}

	@SuppressWarnings("deprecation")
	public void createConsolidatedNotification(NotificationManager mNotificationManager, int updateCount, int newCount, int newNovel) {
		Log.d(TAG, "set consolidated Notification");
		Notification notification = getNotificationTemplate(true);
		CharSequence contentTitle = "BakaReader EX Updates";
		String contentText = "Found";
		if (updateCount > 0) {
			contentText += " " + updateCount + " updated chapter(s)";
		}
		if (newCount > 0) {
			if (updateCount > 0)
				contentText += " and ";
			contentText += " " + newCount + " new chapter(s)";
		}
		if (newNovel > 0) {
			if (updateCount > 0 || newCount > 0)
				contentText += " and ";
			contentText += " " + newNovel + " new novel(s)";
		}
		contentText += ".";

		Intent notificationIntent = new Intent(this, MainTabActivity.class);
		notificationIntent.putExtra(Constants.EXTRA_CALLER_ACTIVITY, UpdateService.class.toString());
		int pendingFlag = PendingIntent.FLAG_CANCEL_CURRENT;
		PendingIntent contentIntent = PendingIntent.getActivity(this, Constants.CONSOLIDATED_NOTIFIER_ID, notificationIntent, pendingFlag);

		notification.setLatestEventInfo(this, contentTitle, contentText, contentIntent);
		mNotificationManager.notify(Constants.CONSOLIDATED_NOTIFIER_ID, notification);
	}

	@SuppressWarnings("deprecation")
	public void prepareNotification(final int notifId, UpdateInfoModel chapter, Notification notification) {
		CharSequence contentTitle = chapter.getUpdateType().toString();
		CharSequence contentText = chapter.getUpdateTitle();

		Intent notificationIntent = new Intent(this, MainTabActivity.class);
		notificationIntent.putExtra(Constants.EXTRA_PAGE, chapter.getUpdatePage());

		int pendingFlag = PendingIntent.FLAG_CANCEL_CURRENT;
		PendingIntent contentIntent = PendingIntent.getActivity(this, notifId, notificationIntent, pendingFlag);

		notification.setLatestEventInfo(this, contentTitle, contentText, contentIntent);
	}

	@SuppressWarnings("deprecation")
	public Notification getNotificationTemplate(boolean firstNotification) {
		int icon = android.R.drawable.arrow_up_float; // Just a placeholder
		CharSequence tickerText = "New Chapters Update";
		long when = System.currentTimeMillis();

		Notification notification = new Notification(icon, tickerText, when);
		if (!PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREF_PERSIST_NOTIFICATION, false)) {
			notification.flags = Notification.FLAG_AUTO_CANCEL;
		}

		notification.defaults = 0;
		if (firstNotification) {
			if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREF_UPDATE_RING, false)) {
				notification.defaults |= Notification.DEFAULT_SOUND;
			}
			if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREF_UPDATE_VIBRATE, false)) {
				notification.defaults |= Notification.DEFAULT_VIBRATE;
			}
		}
		return notification;
	}

	public void updateStatus(String status) {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
		SharedPreferences.Editor editor = sharedPrefs.edit();
		String date = new Date().toString();
		editor.putString(Constants.PREF_RUN_UPDATES, date);
		editor.putString(Constants.PREF_RUN_UPDATES_STATUS, status);
		editor.commit();
		if (notifier != null)
			notifier.onCallback(new CallbackEventData("Last Run: " + date + "\nStatus: " + status));
	}

	private boolean getConsolidateNotificationPref() {
		return PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREF_CONSOLIDATE_NOTIFICATION, true);
	}

	private boolean shouldRun(boolean forced) {
		if (forced) {
			Log.i(TAG, "Forced run");
			return true;
		}

		SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
		String updatesIntervalStr = preferences.getString(Constants.PREF_UPDATE_INTERVAL, "0");

		if (!updatesIntervalStr.equalsIgnoreCase("0")) {
			long lastUpdate = preferences.getLong(Constants.PREF_LAST_UPDATE, 0);
			Date nowDate = new Date();
			long now = nowDate.getTime();

			if (updatesIntervalStr.equalsIgnoreCase("1")) {
				lastUpdate += 15 * 60 * 1000;
			} else if (updatesIntervalStr.equalsIgnoreCase("2")) {
				lastUpdate += 30 * 60 * 1000;
			} else if (updatesIntervalStr.equalsIgnoreCase("3")) {
				lastUpdate += 60 * 60 * 1000;
			} else if (updatesIntervalStr.equalsIgnoreCase("4")) {
				lastUpdate += 12 * 60 * 60 * 1000;
			} else if (updatesIntervalStr.equalsIgnoreCase("5")) {
				lastUpdate += 24 * 60 * 60 * 1000;
			}

			Date lastUpdateDate = new Date(lastUpdate);
			if (lastUpdate <= now) {
				Log.e(TAG, "Updating: " + lastUpdateDate.toLocaleString() + " <= " + nowDate.toLocaleString());
				return true;
			}

			Log.i(TAG, "Next Update: " + lastUpdateDate.toLocaleString() + ", Now: " + nowDate.toLocaleString());
			return false;
		} else {
			Log.i(TAG, "Update Interval set to Never.");
			return false;
		}
	}

	public void setRunning(boolean isRunning) {
		UpdateService.isRunning = isRunning;
	}

	public void setForce(boolean isForced) {
		this.force = isForced;
	}

	public boolean isForced() {
		return force;
	}
}
