﻿using UnityEngine;
using Stove.StoveSDK;
using MiniJSON;
using System.Collections.Generic;
using System;
using System.Collections;
using UnityEngine.Networking;
using UnityEngine.UI;

public class AuthSample : MonoBehaviour
{

    public Toggle maintainGuest;

    public static bool isMaintainGuest;
    public static string environment;
    // Start is called before the first frame update
    void Start()
    {
    }

    // Update is called once per frame
    void Update()
    {
    }

    public void Initialize()
    {
        if (!string.IsNullOrEmpty(environment))
        {
            AuthInitialize();

            return;
        }


        EnvironmentDialog.Show((string packageName, string version, string selectedEnvironment) =>
        { 
            BuildConfiguration buildConfiguration = new BuildConfiguration(packageName, version, selectedEnvironment);
            Constants.SetBuildConfiguration(buildConfiguration);

            if (selectedEnvironment != null)
            {
                environment = selectedEnvironment;

                AuthInitialize();
            }
            else
            {
                // cancel
            }
        });
    }

    public void AuthInitialize()
    {
        Debug.Log("------- [Stove-Sample] Auth.Initialize -------");

        Auth.Initialize(result =>
        {
            if (result.IsSuccessful)
            {
                Debug.Log("------- [Stove-Sample] Auth.Initialize : " + result + " -------");

                SSTools.ShowMessage("Auth.Initialize Success", SSTools.Position.bottom, SSTools.Time.oneSecond);

                Auth.SetPlaytimeListener(playtimeInfo =>
                {
                    foreach (var kvp in playtimeInfo)
                    {
                        Debug.Log("------- [Stove-Sample] Playtime key : " + kvp.Key + ", value : " + kvp.Value + " -------");
                    }
                });
            }
            else
            {
                SSTools.ShowMessage("Auth.Initialize Fail", SSTools.Position.bottom, SSTools.Time.oneSecond);
            }

            OperationUI.HandleResult(result, (Result operationResult) =>
            {
                //Constants.Initialize(environment, (Result constantsResult) =>
                //{
                //    Debug.Log("------- [Stove-Sample] Constants.Initialize : " + constantsResult + " -------");
                //});
            });
        });
    }

    public void Login()
    {
        SelectProviderDialog.Show(provider =>
        {
            if (provider != null)
            {
                Debug.Log("------- [Stove-Sample] Auth.Login -------");

                Auth.Login(provider, (Result result, AccessToken accessToken) =>
                {
                    Debug.Log("------- [Stove-Sample] Auth.Login : " + result + " -------");

                    if (result.IsSuccessful)
                    {
                        SSTools.ShowMessage("Auth.Login Success", SSTools.Position.bottom, SSTools.Time.oneSecond);
                    }
                    else
                    {
                        SSTools.ShowMessage("Auth.Login Fail", SSTools.Position.bottom, SSTools.Time.oneSecond);
                    }
                });
            }
            else
            {
                // cancel
            }
        });
    }

    public void Register()
    {
        SelectProviderDialog.Show(provider =>
        {
            if (provider != null)
            {
                Debug.Log("------- [Stove-Sample] Auth.Register -------");
                TermsOfServiceUI.AgreeForRegister(provider, (Result agreeResult, List<TermsOfServiceData> list) =>
                {
                    if (agreeResult.IsSuccessful)
                    {
                        Auth.Register(provider, list, (Result registerResult, AccessToken accessToken) =>
                        {
                            Debug.Log("------- [Stove-Sample] Auth.Register : " + registerResult + " -------");

                            if (registerResult.IsSuccessful)
                            {
                                SSTools.ShowMessage("Auth.Register Success", SSTools.Position.bottom, SSTools.Time.oneSecond);
                            }
                            else
                            {
                                SSTools.ShowMessage("Auth.Register Fail", SSTools.Position.bottom, SSTools.Time.oneSecond);
                            }
                        });
                    }
                    else
                    {
                        Debug.Log("------- [Stove-Sample] Auth.Register : " + agreeResult + " -------");

                        SSTools.ShowMessage("Auth.Register Fail", SSTools.Position.bottom, SSTools.Time.oneSecond);
                    }
                });
            }
            else
            {
                // cancel
            }
        });
    }

    public void AccessToken()
    {
        AccessToken accessToken = Auth.AccessToken;
        Debug.Log("------- [Stove-Sample] Auth.AccessToken : " + accessToken + " -------");

        SSTools.ShowMessage("Auth.AccessToken : " + accessToken, SSTools.Position.bottom, SSTools.Time.oneSecond);
    }

    public void SaveAccessToken()
    {
        AccessToken accessToken = Auth.AccessToken;
        if (accessToken == null)
        {
            return;
        }
        if (!accessToken.User.IsGuest())
        {
            return;
        }
        Dictionary<string, object> dictionary = accessToken.ToDictionary();
        string accessTokenString = Json.Serialize(dictionary);
        PlayerPrefs.SetString("guest", accessTokenString);
    }

    public bool SetAccessTokenIfPossible()
    {
        Debug.Log("------- [Stove-Sample] SetAccessTokenIfPossible -------");
        string accessTokenString = PlayerPrefs.GetString("guest", "");

        if (!string.IsNullOrEmpty(accessTokenString))
        { 
            AccessToken accessToken = new AccessToken(Json.Deserialize(accessTokenString) as Dictionary<string, object>);
            Auth.AccessToken = accessToken;
            return true;
        } else
        {
            Debug.Log("------- [Stove-Sample] SetAccessTokenIfPossible accessTokenString null -------");
            return false;
        }  
    }

    public void Logout()
    {
        if (maintainGuest.isOn)
        {
            SaveAccessToken();
        }

        Auth.Logout();
        Debug.Log("------- [Stove-Sample] Auth.Logout" + " -------");

        SSTools.ShowMessage("Auth.Logout", SSTools.Position.bottom, SSTools.Time.oneSecond);
    }

    public void Refresh()
    {
        Debug.Log("------- [Stove-Sample] Auth.AccessToken.Refresh -------");

        Auth.AccessToken.Refresh((Result result) =>
        {
            Debug.Log("------- [Stove-Sample] Auth.AccessToken.Refresh : " + result + " -------");

            if (result.IsSuccessful)
            {
                SSTools.ShowMessage("Auth.AccessToken.Refresh Success", SSTools.Position.bottom, SSTools.Time.oneSecond);
            }
            else
            {
                SSTools.ShowMessage("Auth.AccessToken.Refresh Fail", SSTools.Position.bottom, SSTools.Time.oneSecond);
            }
        });
    }

    public void Agree()
    {
        Debug.Log("------- [Stove-Sample] TermsOfServiceUI.Agree -------");

        TermsOfServiceUI.Agree((Result result, List<TermsOfServiceData> list) =>
        {
            Debug.Log("------- [Stove-Sample] TermsOfServiceUI.Agree : " + result + " -------");

            if (result.IsSuccessful)
            {
                SSTools.ShowMessage("TermsOfServiceUI.Agree Success", SSTools.Position.bottom, SSTools.Time.oneSecond);

                foreach (TermsOfServiceData termsOfServiceData in list)
                {
                    Debug.Log("termsOfServiceData : " + termsOfServiceData);
                }
            }
            else
            {
                SSTools.ShowMessage("TermsOfServiceUI.Agree Fail", SSTools.Position.bottom, SSTools.Time.oneSecond);
            }
        });
    }

    public void Fetch()
    {
        Debug.Log("------- [Stove-Sample] TermsOfService.Fetch -------");

        TermsOfService.Fetch((Result result, List<TermsOfServiceData> list) =>
        {
            Debug.Log("------- [Stove-Sample] TermsOfService.Fetch : " + result + " -------");

            if (result.IsSuccessful)
            {
                SSTools.ShowMessage("TermsOfService.Fetch Success", SSTools.Position.bottom, SSTools.Time.oneSecond);

                foreach (TermsOfServiceData termsOfServiceData in list)
                {
                    Debug.Log("termsOfServiceData : " + termsOfServiceData);
                }
            }
            else
            {
                SSTools.ShowMessage("TermsOfService.Fetch Fail", SSTools.Position.bottom, SSTools.Time.oneSecond);
            }
        });
    }

    public void FetchForRegister()
    {
        Debug.Log("------- [Stove-Sample] TermsOfService.FetchForRegister -------");

        TermsOfService.FetchForRegister((Result result, List<TermsOfServiceData> list) =>
        {
            Debug.Log("------- [Stove-Sample] TermsOfService.FetchForRegister : " + result + " -------");

            if (result.IsSuccessful)
            {
                SSTools.ShowMessage("TermsOfService.FetchForRegister Success", SSTools.Position.bottom, SSTools.Time.oneSecond);

                foreach (TermsOfServiceData termsOfServiceData in list)
                {
                    Debug.Log("termsOfServiceData : " + termsOfServiceData);
                }
            }
            else
            {
                SSTools.ShowMessage("TermsOfService.FetchForRegister Fail", SSTools.Position.bottom, SSTools.Time.oneSecond);
            }
        });
    }

    public void SetGameProfile()
    {
        Debug.Log("------- [Stove-Sample] Auth.AccessToken.User.SetGameProfile -------");

        TextFieldTwoDialog.Show("characterNumber", "worldId", (string characterNumber, string worldId) =>
        {
            if (characterNumber == null && worldId == null)
            {
                return;
            }

            GameProfile gameProfile = new GameProfile();
            if (characterNumber != null)
            {
                gameProfile.CharacterNumber = Convert.ToInt64(characterNumber);
            }

            if (worldId != null)
            {
                gameProfile.World = worldId;
            }
            AccessToken accessToken = Auth.AccessToken;
            if (accessToken == null)
            {
                return;
            }
            accessToken.User.GameProfile = gameProfile;
        });
    }

    public void SetGameProfileProperties()
    {
        Debug.Log("------- [Stove-Sample] Auth.AccessToken.User.GameProfile.Properties -------");
        string a = "{\"clan_introduce\": \"Z3VpbGQx\",\"clan_emblem_background\": \"clan_border_base.png\",\"clan_server\": \"한국\",\"clan_limit_level\": 0,\"clan_tag_02\": \"\",\"clan_level\": 16,\"clan_member_max_num\": 30,\"clan_join_approval_type\": \"public\",\"clan_name\": \"guild1\",\"clan_tag_01\": \"\",\"clan_member_num\": 28,\"clan_emblem\": \"clan_normal_1.png\"}";
        TextFieldOneDialog.Show(a, (string properties) =>
        {
            if (properties == null)
            {
                return;
            }
            if (string.IsNullOrEmpty(properties))
            {
                properties = "{}";
            }
            AccessToken accessToken = Auth.AccessToken;
            if (accessToken == null)
            {
                return;
            }
            if (accessToken.User.GameProfile == null)
            {
                GameProfile gameProfile = new GameProfile();
                gameProfile.Properties = Json.Deserialize(properties) as Dictionary<string, object>;
                accessToken.User.GameProfile = gameProfile;
            }
            else
            {
                accessToken.User.GameProfile.Properties = Json.Deserialize(properties) as Dictionary<string, object>;
            }

        });
    }

    public void SetGameProfileDefaultProperties()
    {
        Debug.Log("------- [Stove-Sample] Auth.AccessToken.User.GameProfile.DefaultProperties -------");

        AccessToken accessToken = Auth.AccessToken;
        if (accessToken == null)
        {
            return;
        }
        Dictionary<string, object> defaultDic = new Dictionary<string, object>
        {
            { "clan_introduce", "Z3VpbGQx" },
            { "clan_emblem_background", "clan_border_base.png" },
            { "clan_server", "한국" },
            { "clan_limit_level", 0 },
            { "clan_tag_02", "" },
            { "clan_level", 16 },
            { "clan_member_max_num", 30 },
            { "clan_join_approval_type", "public" },
            { "clan_name", "guild1" },
            { "clan_tag_01", "" },
            { "clan_member_num", 28 },
            { "clan_emblem", "clan_normal_1.png" }
        };
        accessToken.User.GameProfile.Properties = defaultDic;
    }


    public void FetchCharacter()
    {
        StartCoroutine(DoFetchCharacter());
    }

    private IEnumerator DoFetchCharacter()
    {
        string serviceId = Constants.Get("service_id");
        string gatewayUrl = Constants.Get("gateway_url");
        AccessToken accessToken = Auth.AccessToken;
        string token = "";
        long memberNumber = 0;
        if (accessToken != null)
        {
            token = accessToken.Token;
            memberNumber = accessToken.User.MemberNumber;
        }

        bool enable_guid = Constants.Get("enable_guid", false);

        string url = "";
        if (enable_guid)
        {
            url = gatewayUrl + "/mmember/v1.0/character/member_no/" + memberNumber + "?game_id=" + serviceId;
        }
        else
        {
            url = gatewayUrl + "/mmember/v2/character/member_no/" + memberNumber + "?game_id=" + serviceId;
        }
        
        UnityWebRequest request = UnityWebRequest.Get(url);
        request.SetRequestHeader("authorization", "bearer " + token);
        yield return request.SendWebRequest();
        if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.ProtocolError)
        {
            Debug.Log("FetchCharacter : " + request.error);
        }
        else
        {
            Debug.Log("FetchCharacter : " + request.downloadHandler.text);
        }
    }

    public void CreateCharacter()
    {
        TextFieldTwoDialog.Show("nickname", "worldId", (string nickname, string worldId) =>
        {
            if (nickname == null && worldId == null)
            {
                return;
            }
            StartCoroutine(DoCreateCharacter(nickname, worldId));
        });
    }

    public void SignInGPG()
    {
#if UNITY_ANDROID
        AndroidJavaObject wrapper = new AndroidJavaObject("com.stove.unity.UnitySampleWrapper");
        wrapper.CallStatic("initializeGPG");
        wrapper.CallStatic("signInGPG");
#endif
    }

    public void FetchGPGProvider()
    {
#if UNITY_ANDROID
        AndroidJavaObject wrapper = new AndroidJavaObject("com.stove.unity.UnitySampleWrapper");
        string sessionId = wrapper.CallStatic<string>("getSessionId");

        Debug.Log("------- [Stove-Sample] FetchGPGProvider -------");
        Debug.Log("------- [Stove-Sample] FetchGPGProvider sessionId : " + sessionId);

        GPGProvider provider = new GPGProvider(sessionId);
        provider.Fetch((Result result, List<Dictionary<string, object>> accounts) =>
        {
            if (result.IsSuccessful)
            {
                List<string> list = new List<string>();
                foreach (Dictionary<string, object> account in accounts)
                {
                    string recallToken = account["recall_token"] as string;
                    list.Add(recallToken);
                }

                ListDialog.Show(list, (string clickValue) =>
                {
                    if (clickValue == null)
                    {
                        // cancel
                        Debug.Log("------- [Stove-Sample] FetchGPGProvider Cancel -------");
                    }
                    else
                    {
                        foreach (Dictionary<string, object> account in accounts)
                        {
                            string recallToken = account["recall_token"] as string;

                            if (clickValue.Equals(recallToken))
                            {
                                GPGProvider loadProvider = new GPGProvider(sessionId, account);
                                Auth.Login(loadProvider, (Result loginResult, AccessToken accessToken) =>
                                {
                                    Debug.Log("------- [Stove-Sample] GPG Login : " + loginResult + " -------");

                                    if (loginResult.IsSuccessful)
                                    {
                                        SSTools.ShowMessage("GPG Login Success", SSTools.Position.bottom, SSTools.Time.oneSecond);
                                    }
                                    else
                                    {
                                        OperationUI.HandleResult(loginResult, (Result operationResult) =>
                                        {

                                        });
                                    }
                                });
                                break;
                            }
                        }
                    }
                });
            }
            else
            {
                Debug.Log("------- [Stove-Sample] FetchGPGProvider Fail : " + result + " -------");

                OperationUI.HandleResult(result, (Result operationResult) =>
                {

                });
            }
        });
#endif
    }

    public void LoadGPGProvider()
    {
#if UNITY_ANDROID

        AndroidJavaObject wrapper = new AndroidJavaObject("com.stove.unity.UnitySampleWrapper");
        string sessionId = wrapper.CallStatic<string>("getSessionId");

        Debug.Log("------- [Stove-Sample] LoadGPGProvider -------");

        GPGProvider provider = new GPGProvider(sessionId);
        provider.Fetch((Result result, List<Dictionary<string, object>> accounts) =>
        {
            if (result.IsSuccessful)
            {
                if (accounts.Count == 0)
                {
                    Debug.Log("------- [Stove-Sample] LoadGPGProvider : " + result + " -------");
                    SSTools.ShowMessage("LoadGPGProvider Success. But accounts is zero", SSTools.Position.bottom, SSTools.Time.oneSecond);
                }
                else
                {
                    Dictionary<string, object> account = accounts[0];
                    provider.Load(account, (Result loadResult, GPGProvider loadedProvider) =>
                    {
                        if (loadedProvider == null)
                        {
                            // new play
                            Debug.Log("------- [Stove-Sample] LoadGPGProvider : " + loadResult + " -------");
                            SSTools.ShowMessage("LoadGPGProvider Success. New Play", SSTools.Position.bottom, SSTools.Time.oneSecond);
                        }
                        else
                        {
                            // load play
                            Auth.Login(loadedProvider, (Result loginResult, AccessToken accessToken) =>
                            {
                                Debug.Log("------- [Stove-Sample] GPG Login : " + loginResult + " -------");

                                if (loginResult.IsSuccessful)
                                {
                                    SSTools.ShowMessage("LoadGPGProvider GPG Login", SSTools.Position.bottom, SSTools.Time.oneSecond);
                                }
                                else
                                {
                                    OperationUI.HandleResult(loginResult, (Result operationResult) =>
                                    {

                                    });
                                }
                            });
                        }
                    });
                }
            }
            else
            {
                Debug.Log("------- [Stove-Sample] LoadGPGProvider Fail : " + result + " -------");

                OperationUI.HandleResult(result, (Result operationResult) =>
                {

                });
            }
        });
#endif
    }

    public void LinkGPGProvider()
    {
#if UNITY_ANDROID

        AndroidJavaObject wrapper = new AndroidJavaObject("com.stove.unity.UnitySampleWrapper");
        string sessionId = wrapper.CallStatic<string>("getSessionId");

        Debug.Log("------- [Stove-Sample] LinkGPGProvider -------");

        GPGProvider provider = new GPGProvider(sessionId);

        Auth.AccessToken.User.Link(provider, (Result result) =>
        {
            Debug.Log("------- [Stove-Sample] LinkGPGProvider : " + result + " -------");

            if (result.IsSuccessful)
            {
                SSTools.ShowMessage("LinkGPGProvider Success", SSTools.Position.bottom, SSTools.Time.oneSecond);
            }
            else
            {
                OperationUI.HandleResult(result, (Result operationResult) =>
                {

                });
            }
        });
#endif
    }

    private IEnumerator DoCreateCharacter(string nickname, string worldId)
    {
        string serviceId = Constants.Get("service_id");
        string gatewayUrl = Constants.Get("gateway_url");
        AccessToken accessToken = Auth.AccessToken;
        string token = "";
        long memberNumber = 0;
        if (accessToken != null)
        {
            token = accessToken.Token;
            memberNumber = accessToken.User.MemberNumber;
        }

        Dictionary<string, object> dictionary = new Dictionary<string, object>();
        dictionary.Add("member_no", memberNumber);
        dictionary.Add("game_id", serviceId);
        dictionary.Add("nickname", nickname);
        dictionary.Add("world_id", worldId);
        dictionary.Add("channel_id", "");

        bool enable_guid = Constants.Get("enable_guid", false);

        string url = "";
        if (enable_guid)
        {
            dictionary.Add("guid_yn", "Y");
            url = gatewayUrl + "/mmember/v1.0/character";
        }
        else
        {
            url = gatewayUrl + "/mmember/v2/character";
        }
    
        UnityWebRequest request = new UnityWebRequest(url, "POST");
        request.SetRequestHeader("authorization", "bearer " + token);
        request.SetRequestHeader("Content-Type", "application/json");

        request.uploadHandler = (UploadHandler)new UploadHandlerRaw(new System.Text.UTF8Encoding().GetBytes(Json.Serialize(dictionary)));
        request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();

        yield return request.SendWebRequest();
        if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.ProtocolError)
        {
            Debug.Log("CreateCharacter : " + request.error);
        }
        else
        {
            Debug.Log("CreateCharacter : " + request.downloadHandler.text);
        }
    }

	public void Version()
    {
        SSTools.ShowMessage("Auth Version : " + Auth.GetVersion(), SSTools.Position.bottom, SSTools.Time.oneSecond);

        bool isMain =  Auth.IsMain("APPLE");
        if (isMain)
        {
            SSTools.ShowMessage("isLinkState TRUE", SSTools.Position.bottom, SSTools.Time.oneSecond);
        }
        else
        {
            SSTools.ShowMessage("islinkState FALSE", SSTools.Position.bottom, SSTools.Time.oneSecond);
        }
    }

    public void onMaintainGuest()
    {
        SSTools.ShowMessage("maintainGuest Duplicate", SSTools.Position.bottom, SSTools.Time.oneSecond);
    }
}
