package com.example.demotunnel;

import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.InputStreamReader;

import com.peergine.tunnel.android.pgJniTunnel;

import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.AssetManager;
import android.graphics.Color;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {

	private android.widget.EditText m_editSvrAddr;
	private android.widget.EditText m_editRlyAddr;
	private android.widget.EditText m_editLocalDevID;
	private android.widget.Button m_btnStart;
	private android.widget.Button m_btnStop;
	private android.widget.EditText m_editRunningStatus;
	private android.widget.EditText m_editSDKVersion;
	private android.widget.EditText m_editComment;

	private android.widget.EditText m_editRemoteDevID;
	private android.widget.EditText m_editRemoteListenAddr;
	private android.widget.EditText m_editLocalClientAddr;
	private android.widget.Button m_btnConnect;
	private android.widget.Button m_btnDisconnect;
	private android.widget.EditText m_editConnectStatus;

	private android.widget.Button m_btnLoginStatus;
	private android.widget.Button m_btnLoginNow;

	private android.widget.EditText m_editRemoteDevID1;
	private android.widget.Button m_btnChannelAuto;
	private android.widget.Button m_btnChannelRelay;

	private android.widget.EditText m_editRemoteDevID2;
	private android.widget.Button m_btnConnectList;
	private android.widget.Button m_btnPeerInfoGet;

	private android.widget.TextView m_textDebugInfo;

	private String m_sPeerID = "";

	// true: Get config parameter from file 'demoTunnel.cfg'
	// false: Get config parameter from 'm_sCfgParamXXX' string.
	private boolean m_bCfgParamFromFile = true;
	
	// Config user account:
	// true: 'Code' Mode
	// false: 'Password' Mode.
	private boolean m_bCfgParamModeCode = true;
	
	// Default server address and regex.
	private String m_sSvrAddrDef = "p2ptun.peergine.com";
	private String m_sSvrAddrDefRegex = "p2ptun\\.peergine\\.com";
	
	// Default relay address and regex.
	private String m_sRlyAddrDef = "rlytun.peergine.com";
	private String m_sRlyAddrDefRegex = "rlytun\\.peergine\\.com";

	// Default username and password and regex.
	private String m_sUsernameDef = "_DEV_user1234@pptun.com";
	private String m_sUsernameDefRegex = "_DEV_user1234@pptun\\.com";

	private String m_sPasswordDef = "pass5678";
	private String m_sPasswordDefRegex = "pass5678";

	// Config param for code mode.
	private String m_sCfgParamCode = ""
		+ "(RelayList){"
		+ "  (Relay0){"
		+ "    (Type){0}"
		+ "    (Addr){" + m_sRlyAddrDef + ":443}"
		+ "  }"
		+ "}"
		+ "(ModeClient){"
		+ "  (Base){"
		+ "    (MaxSess){128}"
		+ "    (MaxHttp){0}"
		+ "    (MaxTunnel){128}"
		+ "    (ConnectTimeout){30}"
		+ "    (SessBufSize){256}"
		+ "    (P2PTryTime){1}"
		+ "    (LoginDelayInterval){1}"
		+ "    (LoginDelayMax){30}"
		+ "  }"
		+ "  (Node){"
		+ "    (SvrAddr){" + m_sSvrAddrDef + ":7885}"
		+ "    (CltAddr){0:0:0:127.0.0.1:0:0}"
		+ "    (SvrName){pgTunnelSvr0}"
		+ "    (ClientOnly){0}"
		+ "  }"
		+ "  (AccountCode){" // ID code mode.
		+ "    (Prefix){_DEV_}"
		+ "    (Domain){pptun.com}"
		+ "    (Comment){tunnel client for Android}"
		+ "  }"
		+ "  (Log){"
		+ "    (Level0){1}"
		+ "    (Level1){1}"
		+ "    (Level2){1}"
		+ "    (Level3){1}"
		+ "    (Debug){1}"
		+ "  }"
		+ "  (NetCardFilter){"
		+ "    (Mode){0}"
		+ "    (List){}"
		+ "  }"
		+ "  (Utilize){"
		+ "    (ForwardSpeed){0}"
		+ "    (DirectTunnelEnable){1}"
		+ "  }"
		+ "}";

	// Config param for password mode.
	private String m_sCfgParamPass = ""
		+ "(RelayList){"
		+ "  (Relay0){"
		+ "    (Type){0}"
		+ "    (Addr){" + m_sRlyAddrDef + ":443}"
		+ "  }"
		+ "}"
		+ "(ModeClient){"
		+ "  (Base){"
		+ "    (MaxSess){128}"
		+ "    (MaxHttp){0}"
		+ "    (MaxTunnel){128}"
		+ "    (ConnectTimeout){30}"
		+ "    (SessBufSize){256}"
		+ "    (P2PTryTime){1}"
		+ "    (LoginDelayInterval){1}"
		+ "    (LoginDelayMax){30}"
		+ "  }"
		+ "  (Node){"
		+ "    (SvrAddr){" + m_sSvrAddrDef + ":7885}"
		+ "    (CltAddr){0:0:0:127.0.0.1:0:0}"
		+ "    (SvrName){pgTunnelSvr0}"
		+ "    (ClientOnly){0}"
		+ "  }"
		+ "  (AccountPass){"  // Password mode.
		+ "    (User){" + m_sUsernameDef + "}"  // user name
		+ "    (Pass){" + m_sPasswordDef + "}"  // password.
		+ "    (Comment){tunnel client for Android}"
		+ "  }"
		+ "  (Log){"
		+ "    (Level0){1}"
		+ "    (Level1){1}"
		+ "    (Level2){1}"
		+ "    (Level3){1}"
		+ "    (Debug){1}"
		+ "  }"
		+ "  (NetCardFilter){"
		+ "    (Mode){0}"
		+ "    (List){}"
		+ "  }"
		+ "  (Utilize){"
		+ "    (ForwardSpeed){0}"
		+ "    (DirectTunnelEnable){1}"
		+ "  }"
		+ "}";

	
	private BroadcastReceiver m_BroadcastReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
    	   String sAct = intent.getAction();
    	   if (sAct.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
    		   boolean bIsConnected = false;
    		   ConnectivityManager conMag = (ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE);
    		   if (conMag != null) {
    			   // Get all network connections, include wifi and mobile
    			   NetworkInfo[] infos = conMag.getAllNetworkInfo();
    			   if (infos != null) {
    				   for (int i = 0; i < infos.length; i++) {
    					   // Check if it is connected
    					   if (infos[i].getState() == NetworkInfo.State.CONNECTED) {
    						   bIsConnected = true;
    						   break;
    					   }
    				   }
    			   }
    		   }
    		   if (bIsConnected) {
    			   pgJniTunnel.Control(pgJniTunnel.PG_TUNNEL_CONTROL_LOGIN_NOW, "");
    	   		   Toast.makeText(MainActivity.this, "Network connected", Toast.LENGTH_SHORT).show();
    		   }
    	   }
		}
	};
	
	private void ReceiveRegister() {
		IntentFilter intentFilter = new IntentFilter();
		intentFilter.addAction(Intent.ACTION_SCREEN_ON);
		intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
		registerReceiver(m_BroadcastReceiver, intentFilter);		
	}

	private void ReceiveUnregister() {
		unregisterReceiver(m_BroadcastReceiver);
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		m_editSvrAddr = (android.widget.EditText)findViewById(R.id.editSvrAddr);
		m_editRlyAddr = (android.widget.EditText)findViewById(R.id.editRlyAddr);
		m_editLocalDevID = (android.widget.EditText)findViewById(R.id.editLocalDevID);

		m_btnStart = (android.widget.Button)findViewById(R.id.btnStart);
		m_btnStart.setOnClickListener(m_OnClink);
		m_btnStop = (android.widget.Button)findViewById(R.id.btnStop);
		m_btnStop.setOnClickListener(m_OnClink);

		m_editRunningStatus = (android.widget.EditText)findViewById(R.id.editRunningStatus);
		m_editSDKVersion = (android.widget.EditText)findViewById(R.id.editSDKVersion);
		m_editComment = (android.widget.EditText)findViewById(R.id.editComment);

		m_editRemoteDevID = (android.widget.EditText)findViewById(R.id.editRemoteDevID);
		m_editRemoteListenAddr = (android.widget.EditText)findViewById(R.id.editListenAddr);
		m_editLocalClientAddr = (android.widget.EditText)findViewById(R.id.editClientAddr);

		m_btnConnect = (android.widget.Button)findViewById(R.id.btnCnntAdd);
		m_btnConnect.setOnClickListener(m_OnClink);
		m_btnDisconnect = (android.widget.Button)findViewById(R.id.btnCnntDelete);
		m_btnDisconnect.setOnClickListener(m_OnClink);

		m_editConnectStatus = (android.widget.EditText)findViewById(R.id.editConnectStatus);

		m_btnLoginStatus = (android.widget.Button)findViewById(R.id.btnLoginStatus);
		m_btnLoginStatus.setOnClickListener(m_OnClink);
		m_btnLoginNow = (android.widget.Button)findViewById(R.id.btnLoginNow);
		m_btnLoginNow.setOnClickListener(m_OnClink);

		m_editRemoteDevID1 = (android.widget.EditText)findViewById(R.id.editRemoteDevID1);
		m_btnChannelAuto = (android.widget.Button)findViewById(R.id.btnChannelAuto);
		m_btnChannelAuto.setOnClickListener(m_OnClink);
		m_btnChannelRelay = (android.widget.Button)findViewById(R.id.btnChannelRelay);
		m_btnChannelRelay.setOnClickListener(m_OnClink);

		m_editRemoteDevID2 = (android.widget.EditText)findViewById(R.id.editRemoteDevID2);
		m_btnConnectList = (android.widget.Button)findViewById(R.id.btnConnectList);
		m_btnConnectList.setOnClickListener(m_OnClink);
		m_btnPeerInfoGet = (android.widget.Button)findViewById(R.id.btnPeerInfoGet);
		m_btnPeerInfoGet.setOnClickListener(m_OnClink);

		m_textDebugInfo = (android.widget.TextView)findViewById(R.id.textDebugInfo);

		m_editSvrAddr.setText(m_sSvrAddrDef);
		m_editRlyAddr.setText(m_sRlyAddrDef);

		ReceiveRegister();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

    @Override
    protected void onDestroy() {
        ReceiveUnregister();
    	TunnelStop();
        super.onDestroy();
    }
	
    @Override
    protected void onStart() {
       super.onStart();
	   pgJniTunnel.Control(pgJniTunnel.PG_TUNNEL_CONTROL_LOGIN_NOW, "");
	   Toast.makeText(MainActivity.this, "Enter foreground", Toast.LENGTH_SHORT).show();
    }

    private String CfgFileLoadDef() {
    	String sCfgParam = "";

       	AssetManager assetMng = getAssets();
        try {
        	InputStream in = assetMng.open("demoTunnel.cfg");           
        	BufferedReader br = new BufferedReader(new InputStreamReader(in));

        	String sLine;
            while ((sLine = br.readLine()) != null) {
            	sCfgParam += sLine;
            }
  
            in.close();
        }
        catch (Exception e) {
            e.printStackTrace();
            sCfgParam = "";
        }
   	
        return sCfgParam;
    }
    
    private String CfgFileSave(String sCfgParam) {
       	String sFilePath = "";
       	
       	try {
	       	sFilePath = getFilesDir().getAbsolutePath() + "/demoTunnel.cfg";
	       	FileWriter fileWR = new FileWriter(sFilePath);
			fileWR.write(sCfgParam);
			fileWR.close();
       	}
        catch (Exception e) {
            e.printStackTrace();
            sFilePath = "";
        }
   	
       	return sFilePath;
    }
    
    private String CfgFileReplaceAddrInfo(String sCfgParam, String sSvrAddr, String sRlyAddr) {
    	String sCfgParamNew = "";

    	try {
    		sCfgParamNew = sCfgParam.replaceAll(m_sSvrAddrDefRegex, sSvrAddr);
     		sCfgParamNew = sCfgParamNew.replaceAll(m_sRlyAddrDefRegex, sRlyAddr);
   	}
        catch (Exception e) {
            e.printStackTrace();
            sCfgParamNew = "";
        }
   	
    	return sCfgParamNew;
    }

    private String CfgFileReplaceUserInfo(String sCfgParam, String sUsername, String sPassword) {
    	String sCfgParamNew = "";

    	try {
    		sCfgParamNew = sCfgParam.replaceAll(m_sUsernameDefRegex, sUsername);
    		sCfgParamNew = sCfgParamNew.replaceAll(m_sPasswordDefRegex, sPassword);
   	}
        catch (Exception e) {
            e.printStackTrace();
            sCfgParamNew = "";
        }
   	
    	return sCfgParamNew;
    }

    // Get MAC address.
    private String getMacAddr(){
        String macAddress = "";

        try {
	        WifiManager wm = (WifiManager)getSystemService(Context.WIFI_SERVICE);
	        if (wm != null) {
		        WifiInfo info = wm.getConnectionInfo();
		        if (info != null) {
		            macAddress = info.getMacAddress();
		            macAddress = macAddress.replace(":", "").toUpperCase();
		        }
	        }
        }
        catch (Exception ex) {
        	macAddress = "";
        }

        return macAddress;
    }

 	public boolean onKeyUp(int keyCode, KeyEvent event) {
	    if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
			Log.d("demoTunnel", "onKeyDown, KEYCODE_BACK");
	      	ExitDialog();
      		return true;
	    }
	    return super.onKeyUp(keyCode, event);
	}
	private DialogInterface.OnClickListener m_DlgClick = new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
        	if (which == AlertDialog.BUTTON_POSITIVE) {
        		TunnelStop();
        		android.os.Process.killProcess(android.os.Process.myPid());  
        	}
        }
    };
	public void ExitDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);  
        builder.setTitle("Confirm");  
        builder.setMessage("Are you sure to exit?");  
        builder.setPositiveButton("YES", m_DlgClick);  
        builder.setNegativeButton("NO", m_DlgClick);
        builder.show(); 
	}
	
    private void Alert(String sTitle, String sMsg) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);  
        builder.setTitle(sTitle);  
        builder.setMessage(sMsg);  
        builder.setPositiveButton("OK", null);
        builder.show();
	}

	private android.view.View.OnClickListener m_OnClink = new android.view.View.OnClickListener() {
		// Control clicked
		public void onClick(View args0) {
			switch (args0.getId()) {
			case R.id.btnStart:
				TunnelStart();
				break;

			case R.id.btnStop:
				TunnelStop();
				break;

			case R.id.btnCnntAdd:
				ConnectAdd();
				break;

			case R.id.btnCnntDelete:
				ConnectDelete();
				break;

			case R.id.btnLoginStatus:
				LoginStatusGet();
				break;

			case R.id.btnLoginNow:
				LoginNow();
				break;

			case R.id.btnChannelAuto:
				ChannelSetAuto();
				break;

			case R.id.btnChannelRelay:
				ChannelSetRelay();
				break;

			case R.id.btnConnectList:
				ConnectList();
				break;

			case R.id.btnPeerInfoGet:
				PeerInfoGet();
				break;

			default:
				break;
			}
		}
	};
	
	// event callback
	private Handler m_hdrEventCB = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			Toast.makeText(MainActivity.this, "Callback: event=" + msg.what
				+ ", param=" + (String)(msg.obj), Toast.LENGTH_SHORT).show();			
		}
	};

	private pgJniTunnel.OnCallback m_eventCB = new pgJniTunnel.OnCallback() {
		public void EventProc(int iEvent, String sParam) {
			try {
				Message msg = new Message();
				msg.what = iEvent;
				msg.obj = sParam;
				m_hdrEventCB.sendMessage(msg);
			}
			catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	};
	
	private void TunnelStart() {

        String sSvrAddr = m_editSvrAddr.getText().toString();
		sSvrAddr = sSvrAddr.trim();
		int iInd = sSvrAddr.indexOf(':');
		if (iInd > 0) {
			sSvrAddr = sSvrAddr.substring(0, iInd);
		}

		// Set to default server address.
		if (sSvrAddr.equals("")) {
			sSvrAddr = m_sSvrAddrDef;
		}

        String sRlyAddr = m_editRlyAddr.getText().toString();
		sRlyAddr = sRlyAddr.trim();
		iInd = sRlyAddr.indexOf(':');
		if (iInd > 0) {
			sRlyAddr = sRlyAddr.substring(0, iInd);
		}

		// Set to default server address.
		if (sRlyAddr.equals("")) {
			sRlyAddr = m_sRlyAddrDef;
		}

        Log.d("demoTunnel", "sSvrAddr: " + sSvrAddr + ", sRlyAddr: " + sRlyAddr);

        // Replace server address in config parameter
		String sCfgFilePath = "";
		if (m_bCfgParamFromFile) {
			String sCfgParam = CfgFileLoadDef();
			sCfgParam = CfgFileReplaceAddrInfo(sCfgParam, sSvrAddr, sRlyAddr);
			sCfgFilePath = CfgFileSave(sCfgParam);
			if (sCfgFilePath.equals("")) {
				Alert("Error", "Save config param to file failed");
				return;
			}

			Log.d("demoTunnel", "sCfgParam: " + sCfgParam);
		}
		else {
			if (m_bCfgParamModeCode) {
				String sCfgParam = m_sCfgParamCode;
				sCfgParam = CfgFileReplaceAddrInfo(sCfgParam, sSvrAddr, sRlyAddr);
				if (sCfgParam.equals("")) {
					Alert("Error", "Replace server address failed");
					return;
				}

				int iRet = pgJniTunnel.SetCfgParam(sCfgParam);
				if (iRet != pgJniTunnel.PG_TUNNEL_ERROR_OK) {
					Alert("Error", "Set config param failed");
					return;				
				}

		        Log.d("demoTunnel", "sCfgParam: " + sCfgParam);
			}
			else {
				String sCfgParam = m_sCfgParamPass;
				sCfgParam = CfgFileReplaceAddrInfo(sCfgParam, sSvrAddr, sRlyAddr);
				if (sCfgParam.equals("")) {
					Alert("Error", "Replace server address failed");
					return;
				}

				// Modify the username and passward.
				sCfgParam = CfgFileReplaceUserInfo(sCfgParam, "_DEV_00000@pptun.com", "1234567890");
				if (sCfgParam.equals("")) {
					Alert("Error", "Replace user info failed");
					return;
				}

				int iRet = pgJniTunnel.SetCfgParam(sCfgParam);
				if (iRet != pgJniTunnel.PG_TUNNEL_ERROR_OK) {
					Alert("Error", "Set config param failed");
					return;				
				}

				Log.d("demoTunnel", "sCfgParam: " + sCfgParam);
			}
		}

        String sLocalDevID = m_editLocalDevID.getText().toString();
		sLocalDevID = sLocalDevID.trim();
		if (sLocalDevID.equals("")) {
			Alert("Error", "Local device id is empty");
			return;
		}

        String sSysInfo = "(DevID){" + sLocalDevID
        	+ "}(MacAddr){" + getMacAddr() + "}(CpuMHz){0}"
        	+ "(MemSize){0}(BrwVer){}(OSVer){}(OSSpk){}(OSType){Android}";

        Log.d("demoTunnel", "sCfgPath:" + sCfgFilePath + ", sSysInfo:" + sSysInfo);
        
        // Set event callback
        pgJniTunnel.CallbackSet(m_eventCB);

        // Initialize tunnel sdk
        int iErr = pgJniTunnel.Start(sCfgFilePath, sSysInfo);
		if (iErr != 0) {
			Log.d("demoTunnel", "pgJniTunnel.Start: iError=" + iErr);
			return;
		}

		// Tunnel running...
		m_editRunningStatus.setText("Tunnel is running.");

		// Test VersionGet()
		pgJniTunnel.OutVersion resVer = new pgJniTunnel.OutVersion();
		iErr = pgJniTunnel.VersionGet(resVer);
		if (iErr != 0) {
			Alert("demoTunnel", "VersionGet, iError=" + iErr);
		}
		else {
			m_editSDKVersion.setText(resVer.sVersion);
			Log.d("demoTunnel", "VersionGet, sVer=" + resVer.sVersion);
		}

		// Test CommentGet()
		pgJniTunnel.OutComment resCmt = new pgJniTunnel.OutComment();
		iErr = pgJniTunnel.CommentGet(resCmt);
		if (iErr != 0) {
			Alert("demoTunnel", "CommentGet, iError=" + iErr);
		}
		else {
			m_editComment.setText(resCmt.sComment);
			Log.d("demoTunnel", "CommentGet, sCmt=" + resCmt.sComment);
		}
	}
    
	private void TunnelStop() {

    	pgJniTunnel.Stop();		

		// Tunnel running...
		m_editRunningStatus.setText("Tunnel is stop.");
	}
	
	private void ConnectAdd() {
		
		m_sPeerID = m_editRemoteDevID.getText().toString();
		m_sPeerID = m_sPeerID.trim();
		if (m_sPeerID.equals("")) {
			Alert("Error", "Remote device id is empty");
			return;
		}
		
		String sListenAddr = m_editRemoteListenAddr.getText().toString();
		if (sListenAddr.equals("")) {
			Alert("Error", "Remote listen address is empty");
			return;
		}
		if (sListenAddr.indexOf(':') < 0) {
			Alert("Error", "Invalid listen address! Format is 'x.x.x.x:y'");
			return;			
		}

		String sClientAddr = m_editLocalClientAddr.getText().toString();
		if (!sClientAddr.equals("")
			&& sClientAddr.indexOf(':') < 0)
		{
			Alert("Error", "Invalid client address! Format is 'x.x.x.x:y'");
			return;			
		}

		pgJniTunnel.OutClientAddr resClientAddr = new pgJniTunnel.OutClientAddr();
		int iErr = pgJniTunnel.ConnectAdd("", m_sPeerID, 0,
			0, sListenAddr, sClientAddr, resClientAddr);
		if (iErr != 0) {
			Alert("demoTunnel", "ConnectAdd, iError=" + iErr);
		}
		else {
			m_editLocalClientAddr.setText(resClientAddr.sClientAddr);
			m_editConnectStatus.setText("Connect success");
		}

		// Test ConnectLocalQuery()
		pgJniTunnel.OutConnectInfo resCnntInfo = new pgJniTunnel.OutConnectInfo();
		iErr = pgJniTunnel.ConnectLocalQuery(sClientAddr, resCnntInfo);
		if (iErr != 0) {
			Log.d("demoTunnel", "ConnectLocalQuery, iError=" + iErr);
		}
		else {
			Log.d("demoTunnel", "ConnectLocalQuery, sClientAddr=" + resCnntInfo.sClientAddr);
		}
	}
	
	private void ConnectDelete() {

		m_sPeerID = m_editRemoteDevID.getText().toString();
		m_sPeerID = m_sPeerID.trim();
		if (m_sPeerID.equals("")) {
			Alert("Error", "Remote device id is empty");
			return;
		}
		
		String sClientAddr = m_editLocalClientAddr.getText().toString();
		if (!sClientAddr.equals("")
			&& sClientAddr.indexOf(':') < 0)
		{
			Alert("Error", "Invalid client address! Format is 'x.x.x.x:y'");
			return;			
		}

		int iErr = pgJniTunnel.ConnectLocalDelete("", sClientAddr);
		if (iErr != 0) {
			Alert("demoTunnel", "ConnectLocalDelete, iError=" + iErr);
		}
		else {
			m_editConnectStatus.setText("No connect");
		}

		// Test ConnectLocalQuery()
		pgJniTunnel.OutConnectInfo resCnntInfo = new pgJniTunnel.OutConnectInfo();
		iErr = pgJniTunnel.ConnectLocalQuery(sClientAddr, resCnntInfo);
		if (iErr != 0) {
			Log.d("demoTunnel", "ConnectLocalQuery, iError=" + iErr);
		}
		else {
			Log.d("demoTunnel", "ConnectLocalQuery, sClientAddr=" + resCnntInfo.sClientAddr);
		}
	}
	
	private void LoginStatusGet() {
		pgJniTunnel.OutStatus resStatus = new pgJniTunnel.OutStatus();
		int iErr = pgJniTunnel.StatusGet(0, resStatus);
		if (iErr != 0) {
			Alert("Error", "StatusGet, iError=" + iErr);			
			return;
		}

		Toast.makeText(MainActivity.this, ("Login Status: " + resStatus.iStatus), Toast.LENGTH_SHORT).show();		
	}

	private void LoginNow() {
		int iErr = pgJniTunnel.Control(pgJniTunnel.PG_TUNNEL_CONTROL_LOGIN_NOW, "");
		if (iErr != 0) {
			Alert("Error", "Control, iError=" + iErr);			
			return;
		}

		Toast.makeText(MainActivity.this, "Send login request success", Toast.LENGTH_SHORT).show();		
	}

	private void ChannelSetAuto() {
		String sPeerID = m_editRemoteDevID1.getText().toString();
		sPeerID = sPeerID.trim();
		if (sPeerID.equals("")) {
			m_editRemoteDevID1.setBackgroundColor(Color.YELLOW);
			Alert("Error", "Remote device id is empty");
			m_editRemoteDevID1.requestFocus();
			return;
		}
		else {
			m_editRemoteDevID1.setBackgroundColor(Color.TRANSPARENT);
		}
		
		int iErr = pgJniTunnel.ChannelSet(sPeerID, pgJniTunnel.PG_TUNNEL_CHANNEL_AUTO, "");
		if (iErr != 0) {
			Alert("Error", "ChannelSet, iError=" + iErr);			
			return;
		}
		
		Toast.makeText(MainActivity.this, "Channel set to auto mode", Toast.LENGTH_SHORT).show();
	}

	private void ChannelSetRelay() {
		String sPeerID = m_editRemoteDevID1.getText().toString();
		sPeerID = sPeerID.trim();
		if (sPeerID.equals("")) {
			m_editRemoteDevID1.setBackgroundColor(Color.YELLOW);
			Alert("Error", "Remote device id is empty");
			m_editRemoteDevID1.requestFocus();
			return;
		}
		else {
			m_editRemoteDevID1.setBackgroundColor(Color.TRANSPARENT);
		}
		
		int iErr = pgJniTunnel.ChannelSet(sPeerID, pgJniTunnel.PG_TUNNEL_CHANNEL_RELAY, "");
		if (iErr != 0) {
			Alert("Error", "ChannelSet, iError=" + iErr);			
			return;
		}
		
		Toast.makeText(MainActivity.this, "Channel set to relay mode", Toast.LENGTH_SHORT).show();		
	}

	private void ConnectList() {
		String sRes = "ConnectList: \r\n";
		
		int iInd = 0;
		while (true) {
			pgJniTunnel.OutConnectInfo resConnectInfo = new pgJniTunnel.OutConnectInfo();
			int iErr = pgJniTunnel.ConnectEnum(iInd, resConnectInfo);
			if (iErr != 0) {
				break;
			}
			
			sRes += "Index=" + iInd
				+ "\r\nPeerID=" + resConnectInfo.sPeerID
				+ "\r\nType=" + resConnectInfo.iType
				+ "\r\nEncrypt=" + resConnectInfo.iEncrypt
				+ "\r\nListenAddr=" + resConnectInfo.sListenAddr
				+ "\r\nClientAddr=" + resConnectInfo.sClientAddr
				+ "\r\n";
			
			iInd++;
		}

		m_textDebugInfo.setText(sRes);
		
		if (iInd == 0) {
			Toast.makeText(MainActivity.this, "There is no connect", Toast.LENGTH_SHORT).show();					
		}
	}

	private void PeerInfoGet() {
		String sPeerID = m_editRemoteDevID2.getText().toString();
		sPeerID = sPeerID.trim();
		if (sPeerID.equals("")) {
			m_editRemoteDevID2.setBackgroundColor(Color.YELLOW);
			Alert("Error", "Remote device id is empty");
			m_editRemoteDevID2.requestFocus();
			return;
		}
		else {
			m_editRemoteDevID2.setBackgroundColor(Color.TRANSPARENT);
		}

		pgJniTunnel.OutPeerInfo resPeerInfo = new pgJniTunnel.OutPeerInfo();
		int iErr = pgJniTunnel.PeerInfoGet(sPeerID, resPeerInfo);
		if (iErr != 0) {
			Alert("Error", "PeerInfoGet, iError=" + iErr);
			return;
		}

		String sRes = "PeerInfoGet: "
			+ "\r\nPeerID=" + resPeerInfo.sPeerID			
			+ "\r\nType=" + resPeerInfo.iType
			+ "\r\nAddrLocal=" + resPeerInfo.sAddrLocal
			+ "\r\nAddrRemote=" + resPeerInfo.sAddrRemote
			+ "\r\nTunnelLocal=" + resPeerInfo.sTunnelLocal
			+ "\r\nTunnelRemote=" + resPeerInfo.sTunnelRemote
			+ "\r\nPrivateRemote=" + resPeerInfo.sPrivateRemote;
	
		m_textDebugInfo.setText(sRes);
	}

	private void TestConnect() {
		pgJniTunnel.OutClientAddr resClientAddr = new pgJniTunnel.OutClientAddr();
		int iErr = pgJniTunnel.ConnectAdd("", "test0001", 0,
				0, "127.0.0.1:80", "127.0.0.1:8001", resClientAddr);
		if (iErr != 0) {
			Alert("demoTunnel", "TestConnect: ConnectAdd, iError=" + iErr);
		}
		else {
			m_editLocalClientAddr.setText(resClientAddr.sClientAddr);
			m_editConnectStatus.setText("TestConnect: Connect success");
		}
	}

	private void TestDisconnect() {
		int iErr = pgJniTunnel.ConnectLocalDelete("", "127.0.0.1:8001");
		if (iErr != 0) {
			Alert("demoTunnel", "TestDisconnect: ConnectLocalDelete, iError=" + iErr);
		}
		else {
			m_editConnectStatus.setText("TestDisconnect: No connect");
		}

		try {
			Thread.sleep(300);
		}
		catch (Exception ex) {

		}
	}

    private void TestAllhttpApi() {
    	
		// Test PeerInfoGet()
		pgJniTunnel.OutPeerInfo resPeerInfo = new pgJniTunnel.OutPeerInfo();
		int iErr = pgJniTunnel.PeerInfoGet(m_sPeerID, resPeerInfo);
		if (iErr != 0) {
			Log.d("demoTunnel", "PeerInfoGet, iError=" + iErr);
		}
		else {
			Log.d("demoTunnel", "PeerInfoGet, sPeerID=" + resPeerInfo.sPeerID			
				+ ", iType=" + resPeerInfo.iType
				+ ", sAddrLocal=" + resPeerInfo.sAddrLocal
				+ ", sAddrRemote=" + resPeerInfo.sAddrRemote
				+ ", sTunnelLocal=" + resPeerInfo.sTunnelLocal
				+ ", sTunnelRemote=" + resPeerInfo.sTunnelRemote
				+ ", sPrivateRemote=" + resPeerInfo.sPrivateRemote);
		}

    	iErr = pgJniTunnel.CommentSet("My%20p2p%20tunnel%20client");
		if (iErr != 0) {
			Log.d("demoTunnel", "CommentSet, iError=" + iErr);
		}
    	
		pgJniTunnel.OutDomain resDomain = new pgJniTunnel.OutDomain();
		iErr = pgJniTunnel.DomainGet(resDomain);
		if (iErr != 0) {
			Log.d("demoTunnel", "DomainGet, iError=" + iErr);
		}
		else {
			Log.d("demoTunnel", "DomainGet, sDomain=" + resDomain.sDomain);			
		}

		iErr = pgJniTunnel.DomainSet("123456");
		if (iErr != 0) {
			Log.d("demoTunnel", "DomainSet, iError=" + iErr);
		}

		iErr = pgJniTunnel.TunnelSet("123456", "My%20client");
		if (iErr != 0) {
			Log.d("demoTunnel", "TunnelSet, iError=" + iErr);
		}
		
		pgJniTunnel.OutConnectInfo resConnectInfo = new pgJniTunnel.OutConnectInfo();
		iErr = pgJniTunnel.ConnectLocalQuery("127.0.0.1:8001", resConnectInfo);
		if (iErr != 0) {
			Log.d("demoTunnel", "ConnectLocalQuery, iError=" + iErr);
		}
		else {
			Log.d("demoTunnel", "ConnectLocalQuery, sPeerID=" + resConnectInfo.sPeerID
				+ ", iType=" + resConnectInfo.iType
				+ ", iEncrypt=" + resConnectInfo.iEncrypt
				+ ", sListenAddr=" + resConnectInfo.sListenAddr
				+ ", sClientAddr=" + resConnectInfo.sClientAddr);
		}
		
		iErr = pgJniTunnel.ConnectLocalDelete("", "127.0.0.1:8001");
		if (iErr != 0) {
			Log.d("demoTunnel", "ConnectLocalDelete, iErr=" + iErr);
		}
				
		pgJniTunnel.OutData resReplyData = new pgJniTunnel.OutData();
		iErr = pgJniTunnel.UserExtend("Hello", resReplyData, 5000);
		if (iErr != 0) {
			Log.d("demoTunnel", "UserExtend, iError=" + iErr);
		}
		else {
			Log.d("demoTunnel", "UserExtend, sData=" + resReplyData.sData);
		}

		pgJniTunnel.OutSelf resSelf = new pgJniTunnel.OutSelf();
    	iErr = pgJniTunnel.SelfGet(resSelf);
		if (iErr != 0) {
			Log.d("demoTunnel", "SelfGet, iErr=" + iErr);
		}
		else {
			Log.d("demoTunnel", "SelfGet, Self=" + resSelf.sSelf);
		}

		for (int i = 0; i < 4; i++) {
			iErr = pgJniTunnel.ConnectEnum(i, resConnectInfo);
			if (iErr != 0) {
				Log.d("demoTunnel", "ConnectEnum, Index=" + i + ", iError=" + iErr);
			}
			else {
				Log.d("demoTunnel", "ConnectEnum, Index=" + i
					+ ", sPeerID=" + resConnectInfo.sPeerID
					+ ", iType=" + resConnectInfo.iType
					+ ", iEncrypt=" + resConnectInfo.iEncrypt
					+ ", sListenAddr=" + resConnectInfo.sListenAddr
					+ ", sClientAddr=" + resConnectInfo.sClientAddr);
			}
		}
	}
}
