package com.zzw.packunitydemo;

import org.json.JSONException;
import org.json.JSONObject;

import com.funcell.platform.android.FuncellGameSdkProxy;
import com.funcell.platform.android.event.FuncellEventPublisher;
import com.funcell.platform.android.event.FuncellSDKEventReceiver;
import com.funcell.platform.android.event.Subscribe;
import com.funcell.platform.android.event.ThreadMode;
import com.funcell.platform.android.game.proxy.data.FuncellDataTypes;
import com.funcell.platform.android.game.proxy.data.ParamsContainer;
import com.funcell.platform.android.game.proxy.exit.IFuncellExitCallBack;
import com.funcell.platform.android.game.proxy.init.IFuncellInitCallBack;
import com.funcell.platform.android.game.proxy.init.IPlatformNoticeListCallBack;
import com.funcell.platform.android.game.proxy.init.PlatformParamsType;
import com.funcell.platform.android.game.proxy.pay.FuncellPayParams;
import com.funcell.platform.android.game.proxy.pay.FuncellRoleInfo;
import com.funcell.platform.android.game.proxy.pay.IFuncellPayCallBack;
import com.funcell.platform.android.game.proxy.pay.IFuncellPayListCallBack;
import com.funcell.platform.android.game.proxy.session.FuncellSession;
import com.funcell.platform.android.game.proxy.session.IFuncellSessionCallBack;
import com.unity3d.player.*;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.NativeActivity;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;

public class UnityPlayerNativeActivity extends NativeActivity
{
	private String TAG = getClass().getName().toString();
	private Dialog dialog;
	protected UnityPlayer mUnityPlayer;		// don't change the name of this variable; referenced from native code
	private boolean isInited = false;
	private String mGameObject ="SDK_Object";
	FuncellSession mSession;
	
	// Setup activity layout
	@Override protected void onCreate (Bundle savedInstanceState)
	{
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		super.onCreate(savedInstanceState);

		getWindow().takeSurface(null);
		setTheme(android.R.style.Theme_NoTitleBar_Fullscreen);
		getWindow().setFormat(PixelFormat.RGB_565);

		mUnityPlayer = new UnityPlayer(this);
		if (mUnityPlayer.getSettings ().getBoolean ("hide_status_bar", true))
			getWindow ().setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN,
			                       WindowManager.LayoutParams.FLAG_FULLSCREEN);
		
		setContentView(mUnityPlayer);
		if (!this.isInited)
	    {
			Log.e(TAG,"invoke init by SDK");
			doInit();
			FuncellEventPublisher.getInstance().register(eventReceiver);
	    }
		FuncellGameSdkProxy.getInstance().onCreate(this);
		mUnityPlayer.requestFocus();
	}

	// Quit Unity
	@Override protected void onDestroy ()
	{
		mUnityPlayer.quit();
		FuncellGameSdkProxy.getInstance().onDestroy(this);
		FuncellEventPublisher.getInstance().unregister(eventReceiver);
		super.onDestroy();	
	}

	// Pause Unity
	@Override protected void onPause()
	{
		super.onPause();
		FuncellGameSdkProxy.getInstance().onPause(this);
		mUnityPlayer.pause();
	}

	// Resume Unity
	@Override protected void onResume()
	{
		super.onResume();
		FuncellGameSdkProxy.getInstance().onResume(this);
		mUnityPlayer.resume();
	}

	// This ensures the layout will be correct.
	@Override public void onConfigurationChanged(Configuration newConfig)
	{
		super.onConfigurationChanged(newConfig);
		mUnityPlayer.configurationChanged(newConfig);
	}
	
	

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		// TODO Auto-generated method stub
		super.onSaveInstanceState(outState);
	}

	@Override
	protected void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
		FuncellGameSdkProxy.getInstance().onStart(this);
	}

	@Override
	protected void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
		FuncellGameSdkProxy.getInstance().onStop(this);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// TODO Auto-generated method stub
		super.onActivityResult(requestCode, resultCode, data);
		FuncellGameSdkProxy.getInstance().onActivityResult(this, requestCode, resultCode,
				data);
	}

	@Override
	public void onBackPressed() {
		// TODO Auto-generated method stub
		super.onBackPressed();
	}

	@Override
	protected void onNewIntent(Intent intent) {
		// TODO Auto-generated method stub
		super.onNewIntent(intent);
		FuncellGameSdkProxy.getInstance().onNewIntent(intent);
	}

	@Override
	public void onRequestPermissionsResult(int requestCode,
			String[] permissions, int[] grantResults) {
		// TODO Auto-generated method stub
		super.onRequestPermissionsResult(requestCode, permissions, grantResults);
		FuncellGameSdkProxy.getInstance().onRequestPermissionsResult(requestCode, permissions, grantResults);
	}

	@Override
	protected void onRestart() {
		// TODO Auto-generated method stub
		super.onRestart();
		FuncellGameSdkProxy.getInstance().onRestart(this);
	}

	// Notify Unity of the focus change.
	@Override public void onWindowFocusChanged(boolean hasFocus)
	{
		super.onWindowFocusChanged(hasFocus);
		mUnityPlayer.windowFocusChanged(hasFocus);
	}

	// For some reason the multiple keyevent type is not supported by the ndk.
	// Force event injection by overriding dispatchKeyEvent().
	@Override public boolean dispatchKeyEvent(KeyEvent event)
	{
		if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
			return mUnityPlayer.injectEvent(event);
		return super.dispatchKeyEvent(event);
	}

	// Pass any events not handled by (unfocused) views straight to UnityPlayer
	@Override public boolean onKeyUp(int keyCode, KeyEvent event)     { return mUnityPlayer.injectEvent(event); }
	@Override public boolean onKeyDown(int keyCode, KeyEvent event)   { return mUnityPlayer.injectEvent(event); }
	@Override public boolean onTouchEvent(MotionEvent event)          { return mUnityPlayer.injectEvent(event); }
	/*API12*/ public boolean onGenericMotionEvent(MotionEvent event)  { return mUnityPlayer.injectEvent(event); }
	
	private void doInit() {
		FuncellGameSdkProxy.getInstance().Init(this, new IFuncellInitCallBack(){

			@Override
			public void onInitFailure(String paramString) {
				// TODO Auto-generated method stub
				Log.e(TAG,"-------onInitFailure");
				JSONObject job = new JSONObject();
				try {
					job.put("Init", "onInitFailure");
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				sendMsg2Unity(mGameObject, FuncellSDKUtils.CallbackType.InitCallback, FuncellSDKUtils.ResultCode.Fail.toString(),job.toString());
			}

			@Override
			public void onInitSuccess() {
				// TODO Auto-generated method stub
				Log.e(TAG,"------onInitSuccess");
				JSONObject job = new JSONObject();
				try {
					job.put("Init", "onInitSuccess");
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				sendMsg2Unity(mGameObject, FuncellSDKUtils.CallbackType.InitCallback, FuncellSDKUtils.ResultCode.Success.toString(), job.toString());
			}
			
		}, new IFuncellSessionCallBack(){

			@Override
			public void onLoginSuccess(FuncellSession session) {
				// TODO Auto-generated method stub
				Log.e(TAG,"-------onLoginSuccess");
				Log.e(TAG,"-------session"+session.getmToken());
				mSession = session;
				JSONObject job = new JSONObject();
				try {
					job.put("Login", "onLoginSuccess");
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				sendMsg2Unity(mGameObject, FuncellSDKUtils.CallbackType.LoginCallback,FuncellSDKUtils.ResultCode.Success.toString(), job.toString());
				
			}

			@Override
			public void onLoginCancel() {
				// TODO Auto-generated method stub
				Log.e(TAG,"------onLoginCancel");
				JSONObject job = new JSONObject();
				try {
					job.put("Login", "onLoginCancel");
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				sendMsg2Unity(mGameObject, FuncellSDKUtils.CallbackType.LoginCallback,FuncellSDKUtils.ResultCode.Cancel.toString(), job.toString());
			}

			@Override
			public void onLoginFailed(String paramString) {
				// TODO Auto-generated method stub
				Log.e(TAG,"paramString:"+paramString);
				Log.e(TAG,"------onLoginFailed");
				JSONObject job = new JSONObject();
				try {
					job.put("Login", "onLoginFailed");
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				sendMsg2Unity(mGameObject, FuncellSDKUtils.CallbackType.LoginCallback,FuncellSDKUtils.ResultCode.Fail.toString(), job.toString());
			}

			@Override
			public void onLogout() {
				// TODO Auto-generated method stub
				Log.e(TAG,"------onLogout");
				/**
				 * 游戏需要返回登录界面
				 */
				JSONObject job = new JSONObject();
				try {
					job.put("Logout", "onLogout");
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				sendMsg2Unity(mGameObject, FuncellSDKUtils.CallbackType.LogoutCallback,FuncellSDKUtils.ResultCode.Success.toString(), job.toString());
			}

			@Override
			public void onSwitchAccount(FuncellSession arg0) {
				// TODO Auto-generated method stub
				/**
				 * 切换帐号回调(使用回调信息进行登录验证)
				 * 部分渠道在切换帐号回调中，可能是以登录成功回调来 回调给SDK
				 * 因此当接到该回调信息时候，需要先通知游戏退回登录主界面进行当前角色切换
				 */
				Log.e(TAG,"------onSwitchAccount");
				JSONObject job = new JSONObject();
				try {
					job.put("SwitchAccount", "onSwitchAccount");
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				sendMsg2Unity(mGameObject, FuncellSDKUtils.CallbackType.SwitchAccountCallback,FuncellSDKUtils.ResultCode.Success.toString(), job.toString());
				
			}
			
		}, new IFuncellPayCallBack(){


			@Override
			public void onFail(String paramString) {
				// TODO Auto-generated method stub
				Log.e(TAG,"IFuncellPayCallBack onFail");
				JSONObject job = new JSONObject();
				try {
					job.put("pay", "onFail");
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				sendMsg2Unity(mGameObject, FuncellSDKUtils.CallbackType.PayCallback,FuncellSDKUtils.ResultCode.Fail.toString(), job.toString());
			}

			@Override
			public void onCancel(String paramString) {
				// TODO Auto-generated method stub
				Log.e(TAG,"IFuncellPayCallBack onCancel");
				JSONObject job = new JSONObject();
				try {
					job.put("pay", "onCancel");
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				sendMsg2Unity(mGameObject, FuncellSDKUtils.CallbackType.PayCallback,FuncellSDKUtils.ResultCode.Cancel.toString(), job.toString());
			}

			@Override
			public void onSuccess(String cpOrder, String sdkOrder,
					String extrasParams) {
				// TODO Auto-generated method stub
				/**
				 * 渠道充值成功，不代表游戏服务器到账，请知晓
				 * 返回的参数，如果游戏接入者有自己的逻辑，可以不试用以上参数
				 */
				Log.e(TAG,"IFuncellPayCallBack onSuccess");
				Log.e(TAG,"cpOrder:"+cpOrder); //游戏方的订单，
				Log.e(TAG,"sdkOrder:"+sdkOrder);//平台订单号
				Log.e(TAG,"extrasParams:"+extrasParams);//透传参数
				JSONObject job = new JSONObject();
				try {
					job.put("pay", "onSuccess");
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				sendMsg2Unity(mGameObject, FuncellSDKUtils.CallbackType.PayCallback,FuncellSDKUtils.ResultCode.Success.toString(), job.toString());
			}

			@Override
			public void onClosePayPage(String arg0, String arg1, String arg2) {
				// TODO Auto-generated method stub
				/**
				 * 渠道充值关闭界面
				 * 可能由于某些SDK的支付方式中，采用网页形式进行支付，但是又不能明确支付的状态（成功，失败，取消等）
				 */
				JSONObject job = new JSONObject();
				try {
					job.put("pay", "onClosePayPage");
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				sendMsg2Unity(mGameObject, FuncellSDKUtils.CallbackType.PayCallback,FuncellSDKUtils.ResultCode.Unknown.toString(), job.toString());
			}
			
		});
	}
	
	
	/**
	 * 回调到unity端
	 * @param gameObject
	 * @param type
	 * @param jsonResult
	 */
	private void sendMsg2Unity(String gameObject, FuncellSDKUtils.CallbackType type, String resultCode, String jsonResult) {
		//回调unity端，只用一个Callback方法，通过type来分发数据
		//type_result_jsonResult 方法_结果(0/1/2)_json数据(具体值)
		UnityPlayer.UnitySendMessage(gameObject, "Callback", type.toString() + "_" + resultCode + "_" + jsonResult);
	}
	
	private void sendMsg2Unity(String gameObject, FuncellSDKUtils.CallbackType type, String requestFunction, String resultCode, String result){
		//回调unity端，只用一个Callback方法，通过type来分发数据
		//type_requestFunction_resultCode_jsonResult 方法_结果(0/1/2/3)_json数据(具体值)
		UnityPlayer.UnitySendMessage(gameObject, "CallbackByCallFunction", type.toString() + "_" + requestFunction + "_" + resultCode +"_"+result);
	}
	
	/**
	Unity端调用的android方法，用type来区分
 * @param type
 * @param jsonParam
 */
	public void ClientToSDK(String type, Object... params) {
		switch (type) {
		case "ReqLogin":
			doLogin();
			break;
		case "ReqLogout":
			doLogout();
			break;
		case "ReqExit":
			doExit();
			break;
		case "ReqPay":
			/**
			 * params[0] : 角色信息
			 * params[1] : 支付信息
			 */
			if(params.length > 1){
				doPay((String)params[0], (String)params[1]);
			}
			break;
		case "ReqEveData":
			GetEveData();
			break;
		case "ReqPayList":
			GetPayList();
			break;
		case "ReqCallFunction":
			/**
			 * params[0] : 调用方法名
			 * params[1] : 调用方法对应的json数据参数
			 */
			if(params.length > 1){
				callFunction((String)params[0],params[1]);
			}else{
				callFunction((String)params[0]);
			}
			break;
		default:
			break;
		}
	}
	
	public void callFunction(String functionName,Object... params){
		FuncellGameSdkProxy.getInstance().callFunction(this, functionName, params);
	}
	
	public void doLogin() {
		FuncellGameSdkProxy.getInstance().Login(this);
	}
	
	public void doLogout() {
		FuncellGameSdkProxy.getInstance().Logout(this);
	}
	
	public void doPay(String roleInfoJson, String payJson){
		FuncellRoleInfo roleInfo = new FuncellRoleInfo(); 
		FuncellSDKUtils.ParseJsonAndRunMethod(roleInfo, roleInfoJson);
		
		FuncellPayParams PayParams = new FuncellPayParams();
		FuncellSDKUtils.ParseJsonAndRunMethod(PayParams, payJson);
		PayParams.setmRoleInfo(roleInfo);
		
		FuncellGameSdkProxy.getInstance().Pay(this, PayParams);
	}
	public void doExit() {
		FuncellGameSdkProxy.getInstance().Exit(this, new IFuncellExitCallBack(){

			@Override
			public void onChannelExit() {
				// TODO Auto-generated method stub
				Log.e(TAG, "-------onChannelExit");
				finish();
				android.os.Process.killProcess(android.os.Process.myPid());
			}

			@Override
			public void onGameExit() {
				// TODO Auto-generated method stub
				Log.e(TAG, "-------onGameExit");
				JSONObject job = new JSONObject();
				try {
					job.put("Exit", "onGameExit");
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
//				sendMsg2Unity(mGameObject, "onGameExit", job.toString());
				sendMsg2Unity(mGameObject, FuncellSDKUtils.CallbackType.ExitCallback, FuncellSDKUtils.ResultCode.Success.toString(), job.toString());
				/**
				 * 以下为demo演示，具体游戏自行处理
				 */
						AlertDialog.Builder builder = new Builder(UnityPlayerNativeActivity.this);
						builder.setTitle("游戏退出界面");
						builder.setPositiveButton("退出",
								new DialogInterface.OnClickListener() {

									@Override
									public void onClick(DialogInterface dialog,
											int which) {
										dialog.dismiss();

										/**** 退出逻辑需确保能够完全销毁游戏 ****/
										finish();
										android.os.Process
												.killProcess(android.os.Process
														.myPid());
										/**** 退出逻辑请根据游戏实际情况，勿照搬Demo ****/
									}
								});
						builder.setNegativeButton("取消",
								new DialogInterface.OnClickListener() {

									@Override
									public void onClick(DialogInterface dialog,
											int which) {
										dialog.dismiss();
									}
								});

						dialog = builder.create();
				dialog.show();
				/**
				 * 
				 */
			}
			
		});
	}
	public int GetExitUI() {
		return FuncellGameSdkProxy.getInstance().GetExitUI(this);
	}
	
	/**
	 * Unity端调用sdk方法，用于数据统计
	 * @param dataType 数据类型，对应方法
	 * @param jsonParam json参数
	 */
	public void SetDatas(String dataType, String jsonParam)
	{
		FuncellDataTypes dataTypes = null;
		switch (dataType) {
		case "DATA_LOGIN":
			dataTypes = FuncellDataTypes.DATA_LOGIN;
			break;
		case "DATA_CREATE_ROLE":
			dataTypes = FuncellDataTypes.DATA_CREATE_ROLE;
			break;
		case "DATA_ROLE_LEVELUP":
			dataTypes = FuncellDataTypes.DATA_ROLE_LEVELUP;
			break;
		case "DATA_SERVER_ROLE_INFO":
			dataTypes = FuncellDataTypes.DATA_SERVER_ROLE_INFO;
			break;
		default:
			break;
		}
		FuncellGameSdkProxy.getInstance().setDatas(this, dataTypes, FuncellSDKUtils.ParseJsonToParamsContainer(jsonParam, mSession.getmUserID()));
	}
	
	
	/**以下是可选方法***********************************/
	/**
	 *事件回调注册类
	 */
	FuncellSDKEventReceiver eventReceiver = new FuncellSDKEventReceiver() {
		/**
		 * event="callFunctionCallBack" : callFunction对应的数据回调接口，不能修改
		 * @param requestFunction : 调用callFunction接口方法时，请求的方法名
		 * @param state : 调用callFunction接口方法时，对应的当前请求状态(Success,Fail,Unknown)
		 * @param data : 调用callFunction接口方法时，对应的requestFunction 的数据 ，数据需要根据正确的返回类型进行处理
		 */
		@Subscribe(event="callFunctionCallBack")
		private void callFunctionCallBack(String requestFunction,String state,Object data){
			String res = "";
			/**
			 * 以下为例子,需要对数据进行转换
			 */
			if(data instanceof ParamsContainer){
				ParamsContainer paramsContainer = (ParamsContainer) data;
				JSONObject json = new JSONObject(paramsContainer);
				res = json.toString();
			}else if(data instanceof String){
				res = (String) data;
			}else{
				res = String.valueOf(data);
			}
			sendMsg2Unity(mGameObject,FuncellSDKUtils.CallbackType.CallFunctionCallback,requestFunction,state,res);
		}
	};
	
	/**
	 * EVE数据
	 * @return
	 */
	public void GetEveData()
	{
		String eveJson = FuncellGameSdkProxy.getInstance().GetEveData();
		sendMsg2Unity(mGameObject, FuncellSDKUtils.CallbackType.EveDataCallback, FuncellSDKUtils.ResultCode.Success.toString(), eveJson);
	}
	
	/**
	 * 公告列表
	 * @param type
	 * @param serverID
	 */
	public void RequestNoticeList(String type, String serverID)
	{
		FuncellGameSdkProxy.getInstance().GetNoticeList(this, new IPlatformNoticeListCallBack() {
			
			@Override
			public void onSuccess(String arg0) {
				// TODO Auto-generated method stub
				sendMsg2Unity(mGameObject,FuncellSDKUtils.CallbackType.NoticeListCallback,FuncellSDKUtils.ResultCode.Success.toString(),arg0);
			}
			
			@Override
			public void onFailure(String arg0) {
				// TODO Auto-generated method stub
				sendMsg2Unity(mGameObject,FuncellSDKUtils.CallbackType.NoticeListCallback,FuncellSDKUtils.ResultCode.Fail.toString(),arg0);
			}
		}, type, serverID);
	}
	
	/**
	 * 支付商品列表
	 */
	public void GetPayList()
	{
		FuncellGameSdkProxy.getInstance().GetPayList(this, true, "cash", new IFuncellPayListCallBack() {
			
			@Override
			public void onSuccess(String arg0) {
				// TODO Auto-generated method stub
				sendMsg2Unity(mGameObject, FuncellSDKUtils.CallbackType.PayListCallback, FuncellSDKUtils.ResultCode.Success.toString(), arg0);
			}
			
			@Override
			public void onFail(String arg0) {
				// TODO Auto-generated method stub
				sendMsg2Unity(mGameObject, FuncellSDKUtils.CallbackType.PayListCallback, FuncellSDKUtils.ResultCode.Fail.toString(), arg0);
			}
		});
	}
	
	/**
	 * ClientID
	 */
	public void GetClientID()
	{
		String clientID = FuncellGameSdkProxy.getInstance().GetPlatformParams(this, PlatformParamsType.ClientId);
		sendMsg2Unity(mGameObject, FuncellSDKUtils.CallbackType.ClientIDCallback, FuncellSDKUtils.ResultCode.Success.toString(), clientID);
	}
	
	/**************************************************/
	
	public void ParamsTest(String json){
		Log.e(TAG,"ParamsTest invoke json:"+json);
	}
}
