package de.reinhardt_karlheinz.pcc.android;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Button;
import android.widget.Toast;
import de.reinhardt_karlheinz.pcc.android.servers.USBServer;
import de.reinhardt_karlheinz.pcc.events.PCCMessageEvent;
import de.reinhardt_karlheinz.pcc.events.PCConnectionEvent;
import de.reinhardt_karlheinz.pcc.interfaces.PCCConnection;
import de.reinhardt_karlheinz.pcc.listeners.PCCMsgListener;
import de.reinhardt_karlheinz.pcc.listeners.PCConnectionListener;

/**
 * 
 * (c) Copyright 2012, Karlheinz Reinhardt. All rights reserved.<br>
 * 
 * TODO USE WAIT and NOTIFY instead of synchronized
 * 
 * @author Karlheinz Reinhardt
 * @version 0.0.0.1
 */
public class PCControlActivity extends Activity implements
    PCConnectionListener, PCCMsgListener {
  PCCConnection svr;

  static final String LOG_TAG = "TEST";

  //
  // private ArrayList<HashMap<String, String>> services;
  //
  // private ArrayList<String> categories;

  // private PCCPluginInterface_android service = null;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Toast.makeText(getBaseContext(), "App started", 10000).show();
    Log.i("TEST", "App started");
    svr = new USBServer(38001);
    svr.addPCConnectionListener(PCControlActivity.this);
    svr.addPCCMsgListener(PCControlActivity.this);
    detectPlugins();
    listPlugins();
//    loadPlugins();
    
//    for (PCCPluginConnection pl : pluginConn) {
//      try {
//        pl.getPlugin().onPluginStart();
//      } catch (RemoteException e) {
//        // TODO Auto-generated catch block
//        e.printStackTrace();
//      }
//    }
    // Android_PluginManager plgmngr = new Android_PluginManager(svr,
    // getPackageManager());
    // try {
    // Log.i("TEST", "loading plugins");
    // plgmngr.loadPlugins();
    // Log.i("TEST", "plugin loaded");
    // } catch (FileNotFoundException e1) {
    // // TODO Auto-generated catch block
    // e1.printStackTrace();
    // } catch (IOException e1) {
    // // TODO Auto-generated catch block
    // e1.printStackTrace();
    // } catch (ClassNotFoundException e1) {
    // // TODO Auto-generated catch block
    // e1.printStackTrace();
    // } catch (InstantiationException e1) {
    // // TODO Auto-generated catch block
    // e1.printStackTrace();
    // } catch (IllegalAccessException e1) {
    // // TODO Auto-generated catch block
    // e1.printStackTrace();
    // }
    try {
      svr.startServer();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  private void showToastInUiThread(final String msg, final int lenght) {
    this.runOnUiThread(new Runnable() {
      @Override
      public void run() {
        Toast.makeText(getBaseContext(), msg, lenght).show();
      }
    });
  }

  public static final String ACTION_PICK_PLUGIN = "pcc.intent.action.PICK_PLUGIN";

  ArrayList<HashMap<String, String>> services;

  public void detectPlugins() {
    services = new ArrayList<HashMap<String, String>>();
		PackageManager packageManager = getPackageManager();
    Intent baseIntent = new Intent(ACTION_PICK_PLUGIN);
    List<ResolveInfo> service_list = packageManager.queryIntentServices(
        baseIntent, PackageManager.GET_RESOLVED_FILTER);

    for (ResolveInfo ri : service_list) {
      Log.d(LOG_TAG, ri.toString());
      ServiceInfo sinfo = ri.serviceInfo;
      ApplicationInfo ai = sinfo.applicationInfo;
      IntentFilter filter = ri.filter;
      Log.d(LOG_TAG, sinfo.packageName);
      if (filter != null) {
        HashMap<String, String> item = new HashMap<String, String>();
        Iterator<String> categories = filter.categoriesIterator();
        while (categories.hasNext()) {
          String cat = categories.next();
          Log.d(LOG_TAG, cat);
          if (cat.startsWith("pcc.intent.category.")) {
            // service is a valid pcc plugin
            item.put("categ", cat);
            item.put("pkg", ai.packageName);
            item.put("svname", sinfo.name);
            services.add(item);
          }
        }
      }
    }
  }

  public void listPlugins() {
    Log.d(LOG_TAG, "### listing plugins ###");
    for (HashMap<String, String> item : services) {
      Log.d(LOG_TAG, item.get("categ"));
      Log.d(LOG_TAG, item.get("pkg"));
      Log.d(LOG_TAG, item.get("svname"));
    }
    Log.d(LOG_TAG, "### END PLUGINS ###");
  }

  // /**
  // * interfaces
  // *
  // */
  // private ArrayList<IPCCPlugin> plService = new ArrayList<IPCCPlugin>();

  /**
   * Class for interacting with the main interface of the service.
   */
  // private ArrayList<ServiceConnection> service_connections = new
  // ArrayList<ServiceConnection>();

  // private ServiceConnection svconn = null;
  private ArrayList<PCCPluginConnection> pluginConn = new ArrayList<PCCPluginConnection>();

  public void loadPlugins() {
    // // for (IPCCPlugin plugin : plService) {
    // for (int i = 0; i < services.size(); i++) {
    // svconn = new ServiceConnection() {
    //
    // @Override
    // public void onServiceConnected(ComponentName name, IBinder service) {
    // // TODO Auto-generated method stub
    // plService.add(IPCCPlugin.Stub.asInterface(service));
    // Log.d(LOG_TAG, "onServiceConnected");
    // }
    //
    // @Override
    // public void onServiceDisconnected(ComponentName name) {
    // plService = null;// TODO
    // Log.d(LOG_TAG, "onServiceDisconnected");
    // }
    //
    // };
    // Intent intnt = new Intent(ACTION_PICK_PLUGIN);
    // intnt.addCategory(services.get(i).get("categ"));
    // bindService(intnt, svconn, Context.BIND_AUTO_CREATE);
    // Log.d(LOG_TAG, services.get(i).get("categ"));
    // Log.d(LOG_TAG, services.get(i).get("pkg"));
    // Log.d(LOG_TAG, services.get(i).get("svname"));
    // try {
    // plService.get(i).onPluginStart();
    // } catch (RemoteException e) {
    // // TODO Auto-generated catch block
    // e.printStackTrace();
    // }
    // }
//    PCCPluginConnection pccPlConn;
    for (HashMap<String, String> item : services) {
      Log.i("TEST", "iterate");
      PCCPluginConnection pccPlConn = new PCCPluginConnection();
      Intent i = new Intent(ACTION_PICK_PLUGIN);
      i.addCategory(item.get("categ"));
      bindService(i, pccPlConn, Context.BIND_AUTO_CREATE);
      pluginConn.add(pccPlConn);
    }
  }

  @Override
  public void onPCConnectionEstablished(PCConnectionEvent e) {
    showToastInUiThread("Connection to PC opend", Toast.LENGTH_SHORT);
    Log.i("TEST", "Connection to PC opend");
  }

  @Override
  public void onPCConnectionLost(PCConnectionEvent e) {
    // showToastInUiThread("Connection to PC lost", Toast.LENGTH_SHORT);
    Log.i("TEST", "Connection to PC lost");
    // TODO do not close intent
    this.finish();
  }

  @Override
  public void onMsgReceived(PCCMessageEvent e) {
    // TODO change
    showToastInUiThread("msg: " + e.getMessage(), Toast.LENGTH_SHORT);
    Log.i("TEST", "msgw: " + e.getMessage());
    // for (IPCCPlugin plg : plService) {
    // try {
    // plg.onMessageReceived(e.getMessage());
    // } catch (RemoteException e1) {
    // // TODO Auto-generated catch block
    // e1.printStackTrace();
    // }
    // }
  }

  @Override
  public void onCommandReceived(PCCMessageEvent e) {
    // TODO change
    showToastInUiThread("cmd: " + e.getMessage(), Toast.LENGTH_SHORT);
    Log.i("TEST", "cmd: " + e.getMessage());
  }

}