using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using hive;
using Game;

namespace  GameNetwork
{
    // Game server로의 호출 class
    public class GameConnect : MonoBehaviour {
        
        // delegate format
        public delegate void onGameConnectResult(bool succes);
        public delegate void onGameConnectEvent(bool success, string message);
		public delegate void onGameConnectAccountInfoEvent(bool success, string message, ResponseAccountInfo info);
        public delegate void onGameConnectItemsEvent(int errorCode, string message, List<Item> items, List<GameNetwork.Subscription> subscriptions);
        public delegate void onGameConnectReceiptEvent(bool success, string message, string pid);
        public delegate void onGameConnectSubscriptionReceiptEvent(bool success, string message, string pid, long ownedPlayerId);
        public delegate void onGameConnectPostEvent(bool success, string message, List<Post> posts);

        // delegates
        static event onGameConnectEvent onGameConnectSignIn;
        
        static event onGameConnectResult onGameConnectResetAccount;
        static event onGameConnectEvent onGameConnectDeleteAccount;
        static event onGameConnectEvent onGameConnectSendScore;

		static event onGameConnectAccountInfoEvent onGameConnectAccountInfo;
        
        static event onGameConnectItemsEvent onGameConnectAccountItemsGet;
        static event onGameConnectItemsEvent onGameConnectAccountPurchaseItem;

        static event onGameConnectPostEvent onGameConnectPostCheck;
        static event onGameConnectPostEvent onGameConnectPostReceive;

        // singleton instance
        static GameConnect _instance = null;

        // singleton class method.
        static public GameConnect shared {
            get {
                if (_instance == null) {
                    _instance = FindObjectOfType<GameConnect>();
                    GameObject obj = new GameObject();
                    obj.name = "GameConnect";
                    _instance = obj.AddComponent<GameConnect>();
                    DontDestroyOnLoad(obj);
                }

                return _instance;
            }
        }

        // Game server로 인증을 시도한다.
        public void SignIn(onGameConnectEvent listener) 
        {
            Debug.Log("GameConnect - SignIn");

            onGameConnectSignIn = listener;

            RequestAccountLogin request = new RequestAccountLogin();
            request.PlayerID    = AuthV4.getPlayerInfo().playerId;
            request.AppID       = Configuration.getAppId();
            request.DID         = AuthV4.getPlayerInfo().did;
            request.Nickname    = AuthV4.getPlayerInfo ().playerName;
            request.AuthV4Token = AuthV4.getPlayerInfo ().playerToken;

            request.Request(onGameAccountLogin);
        }

        // Game Server로 계정 정보 초기화를 요청한다.
        public void ResetAccount(onGameConnectResult listener)
        {
            Debug.Log("GameConnect - ResetAccount");

            onGameConnectResetAccount = listener;
            RequestResetAccount request = new RequestResetAccount();
            request.sessionToken = PlayerSettings.Instance().sessionToken;
            request.Request(onGameResetAccount);
        }

        // Game 계정 삭제를 요청한다.
        public void DeleteAccount(onGameConnectEvent listener)
        {
            Debug.Log("GameConnect - DeleteAccount");

            onGameConnectDeleteAccount = listener;
            RequestDeleteAccount request = new RequestDeleteAccount();
            request.sessionToken = PlayerSettings.Instance().sessionToken;
            request.PlayerID    = AuthV4.getPlayerInfo().playerId;
            request.AppID       = Configuration.getAppId();
            request.DID         = AuthV4.getPlayerInfo().did;
            request.AuthV4Token = AuthV4.getPlayerInfo ().playerToken;
            
            request.Request(onGameDeleteAccount);
        }

        // Game server로 score를 전송한다.
        public void SendScore(int score, onGameConnectEvent listener)
        {
            Debug.Log("GameConnect - SendScore");

            onGameConnectSendScore = listener;

            RequestScoreSend request = new RequestScoreSend();
            request.SessionToken = PlayerSettings.Instance().sessionToken;
            request.Score = score;
            request.Request(onGameSendScore);
        }

		// Game server로 사용자 정보를 요청한다.
		public void AccountInfo(long playerId, onGameConnectAccountInfoEvent listener)
		{
			Debug.Log("GameConnect - AccountInfo");

			onGameConnectAccountInfo = listener;

			RequestAccountInfo request = new RequestAccountInfo ();
			request.PlayerID = playerId;
			request.Request (onGameAccountInfo);
		}

        // Game server로 부터 사용자 보유 아이템 항목을 요청한다.
        public void AccountGetItems(onGameConnectItemsEvent listener)
        {
            Debug.Log("GameConnect - GetItems");

            onGameConnectAccountItemsGet = listener;

            RequestAccountGetItems request = new RequestAccountGetItems();
            request.SessionToken = PlayerSettings.Instance().sessionToken;
            request.Request(onGameAccountGetItems);
        }

        // Game server로 아이템 구매를 요청한다.
        public void AccountPurchaseItem(string itemCode, long itemAmount, onGameConnectItemsEvent listener)
        {
            Debug.Log("GameConnect - AccountPurchaseItem");

            onGameConnectAccountPurchaseItem = listener;

            RequestAccountPurchaseItem request = new RequestAccountPurchaseItem();
            request.SessionToken    = PlayerSettings.Instance().sessionToken;
            request.ItemCode        = itemCode;
            request.ItemAmount       = itemAmount;
            request.Request(onGameAccountPurchaseItem);
        }

        // Game server로부터 우편함 목록을 요청한다.
        public void CheckPostbox(onGameConnectPostEvent listener)
        {
            Debug.Log("GameConnect - CheckPostbox");

            onGameConnectPostCheck = listener;

            RequestPostboxPosts request = new RequestPostboxPosts();
            // TODO: server id
            request.SessionToken    = PlayerSettings.Instance().sessionToken;
            request.Request(onGamePostboxPosts);
        }

        // Game server로 우편 수신 처리를 요청한다.
        public void ReceivePost(List<int> postIdList, onGameConnectPostEvent listener)
        {
            Debug.Log("GameConnect - ReceivePost");

            onGameConnectPostReceive = listener;

            RequestPostboxReceive request = new RequestPostboxReceive();
            // TODO: Get session token, server id
            request.SessionToken	= PlayerSettings.Instance().sessionToken;
            request.PostIdList	= postIdList;
            
            request.Request(onGamePostboxReceive);
        }

        // Game server로 IAPV4.IAPV4Receipt 데이터를 전달하여 검증 요청한다.
        public void VerifyReceiptBypassInfo(string bypassInfo, onGameConnectReceiptEvent listener)
        {
            Debug.Log("GameConnect - VerifyReceiptBypassInfo");

            RequestBillingVerify request = new RequestBillingVerify ();

            // require
            request.PlayerID = AuthV4.getPlayerInfo ().playerId;
            request.PurchaseBypassInfo = bypassInfo;

            request.Request ((bool success, string responseString) => {
                    Debug.Log("GameConnect - VerifyReceiptBypassInfo" + responseString);

                    bool isSuccess = false;
                    string message = null;
                    string pid = null;

                    if (success == true) {
                        ResponseBillingVerify response = new ResponseBillingVerify(responseString);

                        if (response.isSuccess() == true) {
                            isSuccess = true;
                            pid = response.marketPid;
                        } else if (response.resultCode == 105) {
                            isSuccess = true;
                            message = response.resultCode.ToString();
                        } else {
                            isSuccess = false;
                            message = response.resultCode.ToString();
                        }
                    } else {
                        isSuccess = false;
                    }

                    listener(isSuccess, message, pid);
                }
            );
        }

        // Game server로 IAPV4.IAPV4Receipt 데이터를 전달하여 검증 요청한다.
        public void VerifyReceipt(IAPV4.IAPV4Receipt receipt, onGameConnectReceiptEvent listener)
        {
            Debug.Log("GameConnect - VerifyReceipt");

            RequestBillingVerify request = new RequestBillingVerify ();

            // require
            request.PlayerID = AuthV4.getPlayerInfo ().playerId;
            request.PurchaseBypassInfo = receipt.bypassInfo;
            request.AppID = Configuration.getAppId ();
            int marketId = 0;
            #if UNITY_ANDROID
            marketId = 2;
            #elif UNITY_IOS
            marketId = 1;
            #endif
            request.MarketID = marketId;
            request.HIVEIAPReceipt = receipt.hiveiapReceipt;
            request.Price = (float)receipt.product.price;
            request.Currency = receipt.product.currency;

            // optional
            //request.AppVersion = Configuration.;
            // request.DID = long.Parse (AuthV4.getPlayerInfo ().did);
            // request.HIVECountry = Configuration.getHiveCountry();
            //request.Country = Configuration
            //request.Language;
            //request.GameLanguage = Configuration.get
            //request.UID;
            //request.DeviceModel =
            //request.OSVersion = Configuration.getv;
            //request.OSAPILevel;
            // request.SDKVersion = Configuration.getHiveSDKVersion();
            //request.ReceiptLevel;

            request.Request ((bool success, string responseString) => {
                    Debug.Log("GameConnect - onGameReceiptVerify" + responseString);

                    bool isSuccess = false;
                    string message = null;
                    string pid = null;

                    if (success == true) {
                        ResponseBillingVerify response = new ResponseBillingVerify(responseString);

                        if (response.isSuccess() == true) {
                            isSuccess = true;
                            pid = response.marketPid;
                        } else if (response.resultCode == 105) {
                            isSuccess = true;
                            message = response.resultCode.ToString();
                        } else {
                            isSuccess = false;
                            message = response.resultCode.ToString();
                        }
                    } else {
                        isSuccess = false;
                    }

                    listener(isSuccess, message, pid);
                }
            );
        }


        public void VerifyReceiptSubscription(IAPV4.IAPV4Receipt receipt, onGameConnectSubscriptionReceiptEvent listener)
        {
            Debug.Log("GameConnect - VerifyReceiptSubscription");

            RequestBillingVerifySubscription request = new RequestBillingVerifySubscription ();

            // require
            request.PlayerID = AuthV4.getPlayerInfo ().playerId;
            request.PurchaseBypassInfo = receipt.bypassInfo;
            request.AppID = Configuration.getAppId ();
            int marketId = 0;
            #if UNITY_ANDROID
            marketId = 2;
            #elif UNITY_IOS
            marketId = 1;
            #endif
            request.MarketID = marketId;
            request.HIVEIAPReceipt = receipt.hiveiapReceipt;
            request.Price = (float)receipt.product.price;
            request.Currency = receipt.product.currency;

            // optional
            //request.AppVersion = Configuration.;
            // request.DID = long.Parse (AuthV4.getPlayerInfo ().did);
            // request.HIVECountry = Configuration.getHiveCountry();
            //request.Country = Configuration
            //request.Language;
            //request.GameLanguage = Configuration.get
            //request.UID;
            //request.DeviceModel =
            //request.OSVersion = Configuration.getv;
            //request.OSAPILevel;
            // request.SDKVersion = Configuration.getHiveSDKVersion();
            //request.ReceiptLevel;

            request.Request ((bool success, string responseString) => {
                    Debug.Log("GameConnect - onGameSubscriptionReceiptVerify" + responseString);

                    bool isSuccess = false;
                    string message = null;
                    string pid = null;
                    long ownedPlayerId = -1;

                    if (success == true) {
                        ResponseBillingVerify response = new ResponseBillingVerify(responseString);

                        if (response.isSuccess() == true) {
                            isSuccess = true;
                            pid = response.marketPid;
                            ownedPlayerId = response.ownedPlayerId;
                        } else if (response.resultCode == 105) {
                            isSuccess = true;
                            message = response.resultCode.ToString();
                        } else {
                            isSuccess = false;
                            message = response.resultCode.ToString();
                        }
                    } else {
                        isSuccess = false;
                    }

                    listener(isSuccess, message, pid, ownedPlayerId);
                }
            );
        }
        

        /*******************************************
        *	Callback
        *******************************************/
        void onGameAccountLogin(bool success, string responseString)
        {
            Debug.Log("GameConnect - onGameAccountLogin" + responseString);

            bool isSuccess = false;
            string message = null;

            if (success == true) {
                ResponseAccountLogin response = new ResponseAccountLogin(responseString);

                if (response.isSuccess() == true) {
                    isSuccess = true;
                    message = "Success";

                    PlayerSettings.Instance().sessionToken = response.sessionToken;
                    PlayerSettings.Instance().Items = response.items;
                    PlayerSettings.Instance().Subscriptions = response.subscriptions;

                } else {
                    isSuccess = false;
                    message = response.resultCode.ToString();
                }
            } else {
                isSuccess = false;
            }

            if (onGameConnectSignIn != null) {
                onGameConnectSignIn(isSuccess, message);
                // onGameConnectSignIn = null;
            }
        } 

        void onGameResetAccount(bool success, string responseString) 
        {
            Debug.Log("GameConnect - onGameResetAccount" + responseString);
            // TODO: Daun 구현 예정

            if (onGameConnectResetAccount != null) {
                onGameConnectResetAccount(success);
            }
        }

        void onGameDeleteAccount(bool success, string responseString) 
        {
            Debug.Log("GameConnect - onGameDeleteAccount" + responseString);

            bool isSuccess = false;
            string message = null;

            if (success == true) {
                Response response = new Response(responseString);

                if (response.isSuccess() == true) {
                    isSuccess = true;
                    message = "Success";

                } else {
                    isSuccess = false;
                    message = response.resultCode.ToString();
                }
            } else {
                isSuccess = false;
            }

            if (onGameConnectDeleteAccount != null) {
                onGameConnectDeleteAccount(isSuccess, message);
            }
        }

        void onGameSendScore(bool success, string responseString)
        {
            Debug.Log("GameConnect - onGameSendScore" + responseString);
            
            bool isSuccess = false;
            string message = null;

            if (success == true) {
                ResponseScoreSend response = new ResponseScoreSend(responseString);
                if (response.isSuccess() == true) {
                    isSuccess = true;
                    message = "Success";
                } else {
                    isSuccess = false;
                    message = response.resultMessage;
                }
            } else {
                isSuccess = false;
                message = "Response failed.";
            }

            if (onGameConnectSendScore != null) {
                onGameConnectSendScore(isSuccess, message);
                // onGameConnectSendScore = null;
            }
        }

		void onGameAccountInfo(bool success, string responseString)
		{
			Debug.Log("GameConnect - onGameAccountInfo" + responseString);

			bool isSuccess = false;
			string message = null;
			ResponseAccountInfo response = null;

			if (success == true) {
				response = new ResponseAccountInfo(responseString);

				if (response.isSuccess() == true) {
					isSuccess = true;
					message = "Success";
				} else {
					isSuccess = false;
					message = response.resultCode.ToString();
				}
			} else {
				isSuccess = false;
			}

            if (onGameConnectAccountInfo != null) {
                onGameConnectAccountInfo(isSuccess, message, response);
                // onGameConnectAccountInfo = null;
            }
		}

        void onGameAccountGetItems(bool success, string responseString)
        {
            Debug.Log("GameConnect - onGameAccountGetItems" + responseString);

            int errorCode = -9998;
            string message = null;
            List<Item> items = null;
            List<GameNetwork.Subscription> subscriptions = null;

            if (success == true) {
                ResponseAccountGetItems response = new ResponseAccountGetItems(responseString);
                errorCode = response.resultCode;

                if (response.isSuccess() == true) {
                    message = "Success";

                    items = response.accountItems;
                    subscriptions = response.subscriptions;

                } else {
                    message = response.resultMessage;
                }
            } else {
                message = "Response failed.";
            }

            if (onGameConnectAccountItemsGet != null) {
                onGameConnectAccountItemsGet(errorCode, message, items, subscriptions);
                //onGameConnectAccountItemsGet = null;
            }
        }

        void onGameAccountPurchaseItem(bool success, string responseString)
        {
            Debug.Log("GameConnect - onGameAccountPurchaseItem" + responseString);

            int errorCode = -9998;
            string message = null;
            List<Item> items = null;

            if (success == true) {
                ResponseAccountPurchaseItem response = new ResponseAccountPurchaseItem(responseString);
                errorCode = response.resultCode;

                if (response.isSuccess() == true) {
                    message = "Success";
                    items = response.items;
                    
                } else {
                    message = response.resultCode.ToString();
                }
            } else {
                message = null;
            }

            if (onGameConnectAccountPurchaseItem != null) {
                onGameConnectAccountPurchaseItem(errorCode, message, items, null);
                // onGameConnectAccountPurchaseItem = null;
            }
        }

        void onGamePostboxPosts(bool success, string responseString)
        {
            Debug.Log("GameConnect - onGamePostboxPosts" + responseString);

            bool isSuccess = false;
            string message = "";
            List<Post> posts = new List<Post> ();

            if (success == true) {
                ResponsePostboxPosts response = new ResponsePostboxPosts(responseString);

                if (response.isSuccess() == true) {
                    isSuccess = true;

                    if (response.posts != null)  {
                        posts = response.posts;
                    }

                } else {
                    isSuccess = false;

                    if (response.resultMessage != null) {
                        message = response.resultCode.ToString();
                    }
                }
            } else {
                isSuccess = false;
                message = "Server Error.\nPlease try again later.";
            }

            if (onGameConnectPostCheck != null) {
                onGameConnectPostCheck(isSuccess, message, (posts.Count > 0) ? posts : null);
                // onGameConnectPostCheck = null;
            }
        }

        void onGamePostboxReceive(bool success, string responseString)
        {
            Debug.Log("GameConnect - onGamePostboxReceive" + responseString);

            bool isSuccess = false;
            string message = null;

            if (success == true) {
                ResponsePostboxReceive response	= new ResponsePostboxReceive(responseString);

                if (response.isSuccess() == true) {
                    isSuccess = true;
                    message = "Success";
                } else {
                    isSuccess = false;
                    message = response.resultMessage;
                }             
            } else {
                isSuccess = false;
                message = "Server Error.\nPlease try again later.";
            }

            if (onGameConnectPostReceive != null) {
                onGameConnectPostReceive(isSuccess, message, null);
                // onGameConnectPostReceive = null;
            }
        }
    }
}