/***
	Copyright (c) 2008 CommonsWare, LLC
	
	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.commonsware.android.service;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.IBinder;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.HashSet;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;

public class MailBuzzService extends Service {
	public static final String IMAP="IMAP";
	public static final String POP3="POP3";
	public static final String PREFS="com.commonsware.android.MailBuzzService";
	public static final int NOTIF_ID=1337;
	public static final String POLL="POLL";
	public static final String SHUTDOWN="SHUTDOWN";
	
	private final IBuzz.Stub binder=new IBuzz.Stub() {
		public void checkNow() {
			checkAccount();
		}
		
		public void enable(boolean enabled) {
			enablePoll(enabled);
		}
		
		public boolean isEnabled() {
			return(getPollState());
		}
	};
	
	private Set<String> messagesSeen=null;
	private ConcurrentLinkedQueue<String> queue=new ConcurrentLinkedQueue<String>();
	private Thread background=null;
	private Timer timer=new Timer(true);
	private TimerTask task=null;
	
	@Override
	public void onCreate() {
		super.onCreate();
		
		background=new Thread(new Runnable() {
			public void run() {
				try {
					String event=null;
					
					while (event!=SHUTDOWN) {
						event=queue.poll();
						
						if (event==POLL) {
							checkAccountImpl();
						}
						else if (event!=SHUTDOWN) {
							Thread.sleep(1000);
						}
					}
				}
				catch (Throwable t) {
					// just end the background thread
				}
			}
		});
		
		background.start();
		setupTimer();
	}
	
	@Override
	public IBinder onBind(Intent intent) {
		return(binder);
	}
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		
		timer.cancel();
		queue.add(SHUTDOWN);
	}
	
	private void checkAccountImpl() {
		SharedPreferences settings=getPrefs();
		String svc_type=settings.getString("type", null);
		String svc_server=settings.getString("server", null);
		String svc_user=settings.getString("user", null);
		String svc_pw=settings.getString("pw", null);
		
		if (svc_type!=null) {
			String[] msgs=null;
			
			try {
				if (svc_type.equals(IMAP)) {
					msgs=MailClient.getIMAPMessageIds(svc_server, svc_user, svc_pw);
				}
				else if (svc_type.equals(POP3)) {
					msgs=MailClient.getPOP3MessageIds(svc_server, svc_user, svc_pw);
				}
				
				Set<String> msgSet=new HashSet<String>();
				
				for (String msg : msgs) {
					msgSet.add(msg);
				}
				
				if (messagesSeen==null) {
					messagesSeen=new CopyOnWriteArraySet<String>(msgSet);
				}
				else if (!messagesSeen.containsAll(msgSet)) {
					showNotification();
					messagesSeen.addAll(msgSet);
				}
			}
			catch (Throwable t) {
				android.util.Log.e("MailBuzz", "Exception fetching mail", t);
			}
		}
	}

	private void checkAccount() {
		queue.add(POLL);
	}
	
	private void enablePoll(boolean enabled) {
		SharedPreferences settings=getPrefs();
		SharedPreferences.Editor editor=settings.edit();
		
		editor.putBoolean("enabled", enabled);
		editor.commit();
		setupTimer();
	}
	
	private boolean getPollState() {
		SharedPreferences settings=getPrefs();
		
		return(settings.getBoolean("enabled", false));
	}
	
	private SharedPreferences getPrefs() {
		return(getSharedPreferences(PREFS, 0));
	}
		
	private void showNotification() {
		NotificationManager nm=(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
		Notification notif=new Notification(
					 this,
					 R.drawable.mail_generic,
					 "New mail!",
					 System.currentTimeMillis(),
					 null, null, null,
					 R.drawable.mail_generic,
					 "MailBuzz",
					 null);

		// after a 100ms delay, vibrate for 250ms, pause for 100 ms and
		// then vibrate for 500ms. Repeat three times.
		
		notif.vibrate = new long[] { 100, 250, 100, 500, 100, 250, 100,
										500, 100, 250, 100, 500 };
		
		nm.notify(NOTIF_ID, notif);
	}
	
	private void setupTimer() {
		if (getPollState()) {
			SharedPreferences settings=getPrefs();
			int pollPeriod=settings.getInt("pollPeriod", 5)*60000;
			
			task=new TimerTask() {
				public void run() {
					checkAccount();
				}
			};
			timer.scheduleAtFixedRate(task, pollPeriod, pollPeriod);
		}
		else if (task!=null) {
			task.cancel();
			task=null;
		}
	}
}