/*
 * Copyright (C) 2009 Google Inc.
 *
 * 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.google.ase;

import java.net.InetSocketAddress;

import android.app.Activity;
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.os.IBinder;
import android.widget.RemoteViews;

import com.google.ase.terminal.Terminal;

/**
 * A service that allows scripts and the RPC server to run in the background.
 *
 * @author Damon Kohler (damonkohler@gmail.com)
 */
public class AseService extends Service {

  private AndroidProxy mAndroidProxy;
  private ScriptLauncher mLauncher;
  private final NotificationManager mNotificationManager;
  private final StringBuilder mNotificationMessage;

  public AseService() {
    mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    mNotificationMessage = new StringBuilder();
  }

  @Override
  public void onStart(Intent intent, int startId) {
    super.onStart(intent, startId);
    if (intent.getAction().equals(Constants.ACTION_LAUNCH_SERVER)) {
      launchServer(intent);
      showNotification();
    } else if (intent.getAction().equals(Constants.ACTION_LAUNCH_SCRIPT)) {
      launchServer(intent);
      launchInterpreter(intent);
      showNotification();
    } else if (intent.getAction().equals(Constants.ACTION_ACTIVITY_RESULT)) {
      mAndroidProxy.onActivityResult(intent.getIntExtra("requestCode", 0), intent.getIntExtra(
          "resultCode", Activity.RESULT_CANCELED), intent.<Intent> getParcelableExtra("data"));
    } else if (intent.getAction().equals(Constants.ACTION_LAUNCH_TERMINAL)) {
      Intent i = new Intent(this, Terminal.class);
      i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      i.putExtras(intent);
      i.putExtra(Constants.EXTRA_PROXY_PORT, mAndroidProxy.getAddress().getPort());
      startActivity(i);
    } else if (intent.getAction().equals(Constants.ACTION_KILL_SERVICE)) {
      stopSelf();
    }
  }

  private void launchInterpreter(Intent intent) {
    if (mLauncher != null) {
      return;
    }
    InetSocketAddress address = mAndroidProxy.getAddress();
    mLauncher = new ScriptLauncher(intent, address);
    try {
      mLauncher.launch();
    } catch (AseException e) {
      AseLog.e(this, e.getMessage(), e);
      stopSelf();
      return;
    }
    mNotificationMessage.append("\nRunning script service: " + mLauncher.getScriptName());
  }

  private void launchServer(Intent intent) {
    if (mAndroidProxy != null) {
      return;
    }
    mAndroidProxy = new AndroidProxy(this, intent);
    boolean usePublicIp = intent.getBooleanExtra(Constants.EXTRA_USE_EXTERNAL_IP, false);
    if (usePublicIp) {
      mAndroidProxy.startPublic();
    } else {
      mAndroidProxy.startLocal();
    }
    InetSocketAddress address = mAndroidProxy.getAddress();
    mNotificationMessage.append(String.format("Running network service on: %s:%d", address
        .getHostName(), address.getPort()));
  }

  private void showNotification() {
    Notification notification =
        new Notification(R.drawable.ase_logo_48, "ASE is running...", System.currentTimeMillis());
    notification.contentView = new RemoteViews(getPackageName(), R.layout.notification);
    notification.contentView.setTextViewText(R.id.notification_title, "ASE Service");
    notification.contentView.setTextViewText(R.id.notification_message, mNotificationMessage
        .toString());
    Intent notificationIntent = new Intent(this, AseService.class);
    notificationIntent.setAction(Constants.ACTION_KILL_SERVICE);
    notification.contentIntent = PendingIntent.getService(this, 0, notificationIntent, 0);
    notification.flags = Notification.FLAG_NO_CLEAR;
    notification.flags = Notification.FLAG_ONGOING_EVENT;
    mNotificationManager.notify(0, notification);
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    if (mLauncher != null) {
      mLauncher.getProcess().kill();
    }
    if (mAndroidProxy != null) {
      mAndroidProxy.shutdown();
    }
    mNotificationManager.cancelAll();
  }

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

@@ -1240,66 +1240,8 @@
 er;%0A
-  private final NotificationManager mNotificationManager;%0A
   pr
@@ -1317,105 +1317,8 @@
 ) %7B%0A
-    mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);%0A
     
@@ -1744,32 +1744,168 @@
 Notification();%0A
+    %7D else if (intent.getAction().equals(Constants.ACTION_LAUNCH_TERMINAL)) %7B%0A      launchServer(intent);%0A      launchTerminal(intent);%0A
     %7D else if (i
@@ -2215,38 +2215,109 @@
 .ACTION_
-LAUNCH_TERMINAL)) %7B%0A  
+KILL_SERVICE)) %7B%0A      stopSelf();%0A    %7D%0A  %7D%0A%0A  private void launchTerminal(Intent intent) %7B%0A
     Inte
@@ -2357,18 +2357,16 @@
 class);%0A
-  
     i.ad
@@ -2404,26 +2404,24 @@
 _TASK);%0A    
-  
 i.putExtras(
@@ -2425,26 +2425,24 @@
 as(intent);%0A
-  
     i.putExt
@@ -2511,18 +2511,16 @@
 ort());%0A
-  
     star
@@ -2537,107 +2537,8 @@
 i);%0A
-    %7D else if (intent.getAction().equals(Constants.ACTION_KILL_SERVICE)) %7B%0A      stopSelf();%0A    %7D%0A
   %7D%0A
@@ -4336,25 +4336,24 @@
 _EVENT;%0A    
-m
 Notification
@@ -4349,24 +4349,124 @@
 otificationM
+anager manager =%0A        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);%0A    m
 anager.notif
@@ -4692,33 +4692,32 @@
 wn();%0A    %7D%0A    
-m
 NotificationMana
@@ -4709,24 +4709,124 @@
 otificationM
+anager manager =%0A        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);%0A    m
 anager.cance

Fix a few null pointer exceptions.