package com.rob57530.smsserver;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Calendar;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.ajax.JSON;

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.AsyncTask;
import android.os.Handler;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.util.Base64;
import android.util.Log;

public class SMSServerService extends Service
{
	private Server m_server = null;
	private int m_port = 0;
	private String m_http = null;
	private String m_name = null;
	private String m_number = null;
	private int m_gateTimeout = -1;

	private NotificationCompat.Builder m_builder = null;
	private NotificationManager m_notificationManager = null;

	private Handler m_handler = null;
	private Runnable m_timer = new Runnable()
	{
		@Override
		public void run()
		{
			register();
		}
	};

	class RequestTask extends AsyncTask<String, String, String>
	{
		@Override
		protected String doInBackground(String... uri)
		{
			Log.d("SMSServerService", "doinbackground");
			HttpClient httpclient = new DefaultHttpClient();
			HttpResponse response;
			String responseString = null;
			try
			{
				HttpGet get = new HttpGet(uri[0]);
				get.setHeader("Host", m_http);
				get.setHeader("Authorization", "Basic " + Base64.encodeToString("__gates__:gatespasswd".getBytes(), Base64.NO_WRAP));

				response = httpclient.execute(get);
				Log.d("SMSServerService", "doinbackground exec");
				StatusLine statusLine = response.getStatusLine();
				if (statusLine.getStatusCode() == HttpStatus.SC_OK)
				{
					ByteArrayOutputStream out = new ByteArrayOutputStream();
					response.getEntity().writeTo(out);
					out.close();
					responseString = out.toString();
				}
				else
				{
					response.getEntity().getContent().close();
					throw new IOException(statusLine.getReasonPhrase());
				}
			}
			catch (ClientProtocolException e)
			{
				Log.d("SMSServerService", "doinbackground:" + e.toString());
				e.printStackTrace();
			}
			catch (IOException e)
			{
				Log.d("SMSServerService", "doinbackground:" + e.toString());
				e.printStackTrace();
			}
			Log.d("SMSServerService", "doinbackground end");
			return responseString;
		}

		@Override
		protected void onPostExecute(String result)
		{
			super.onPostExecute(result);
			if (result != null)
			{
				@SuppressWarnings("unchecked")
				Map<String, Object> root = (Map<String, Object>) JSON.parse(result);
				if (root.containsKey("error"))
				{
					m_gateTimeout = 30;
					Log.w("SMSServer", root.get("error").toString());
					setText("Error: " + root.get("error").toString());
				}
				else
				{
					m_gateTimeout = ((Long) root.get("gateTimeout")).intValue();
					Log.d("SMSServerService", "" + m_gateTimeout);
					setText("Registered. id=" + ((Long) root.get("id")).intValue() + " timeout=" + m_gateTimeout);
				}
			}
			else
			{
				m_gateTimeout = 30;
				setText("Error while registering");
			}
			m_handler.postDelayed(m_timer, Math.max((m_gateTimeout - 20) * 1000, 10000));
		}
	}

	private void setText(String t)
	{
		m_builder.setContentText(t).setOngoing(true).setWhen(Calendar.getInstance().getTimeInMillis());
		Notification n = m_builder.build();
		m_notificationManager.notify(0, n);
		startForeground(0, n);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId)
	{
		if (m_server == null)
		{
			Intent i = new Intent(getApplicationContext(), MainActivity.class);
			i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
			PendingIntent pi = PendingIntent.getActivity(this, 42, i, PendingIntent.FLAG_UPDATE_CURRENT);
			m_builder = new NotificationCompat.Builder(this).setSmallIcon(R.drawable.network_wireless).setContentTitle("SMS Server").setContentIntent(pi);
			m_notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
			setText("Starting...");
			SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(this);
			m_port = p.getInt("port", 0);
			m_http = p.getString("http", "");
			m_name = p.getString("name", "");
			m_number = p.getString("number", "");

			try
			{
				if (m_name.length() == 0)
					throw new Exception("Empty Name");
				if (m_number.length() == 0)
					throw new Exception("Empty Number");
				if (m_port < 1 || m_port > 65535)
					throw new Exception("Invalid Port (1 <= port <= 65535)");
				m_handler = new Handler();
				m_server = new Server(m_port);
				HttpHandler h = new HttpHandler();
				h.setContext(this);
				h.setHttp(m_http);
				m_server.setHandler(h);
				m_server.start();
				if (m_http.length() != 0)
					register();
			}
			catch (Exception e)
			{
				e.printStackTrace();
				setText("Error: " + e.getMessage());
			}
		}
		return Service.START_REDELIVER_INTENT;
	}

	private void register()
	{
		try
		{
			setText("Registering...");
			RequestTask r = new RequestTask();
			r.execute("http://" + m_http + "/register.php?name=" + URLEncoder.encode(m_name, "utf-8") + "&number=" + URLEncoder.encode(m_number, "utf-8")
					+ "&port=" + m_port);
		}
		catch (UnsupportedEncodingException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	public void onDestroy()
	{
		m_handler.removeCallbacks(m_timer);
		m_builder.setOngoing(false);
		m_notificationManager.notify(0, m_builder.build());
		stopForeground(false);
		Log.d("SMSServerService", "stop");
		if (m_server != null)
		{
			try
			{
				m_server.stop();
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
			m_server = null;
		}
		super.onDestroy();
	}

	@Override
	public IBinder onBind(Intent arg0)
	{
		return null;
	}

}
