using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections;
using System.Collections.Generic;
using Games.GlobeDefine;
using Games.ChatHistory;
using Games.Item;
using GCGame.Table;
using GCGame;
using Module.Log;
using Google.ProtocolBuffers;

public class ChatHistoryLogic : MonoBehaviour
{

    public void ShowHistory(int channel)
    {
        _SelectedCannel = channel;
        _FriendGuid = 0;

        UpdateChannelHistory();
    }

    public virtual void ShowHistory(UInt64 friendGuid)
    {
        _FriendGuid = friendGuid;
        _SelectedCannel = (int)GC_CHAT.CHATTYPE.CHAT_TYPE_FRIEND;

        UpdateChannelHistory();
    }

    #region chat history

    public RectTransform _ChatSliderRect;
    public RectTransform _ChatLogContent;
    public GameObject _NewLogGO;
    public Text _NewLogTip;
    public GameObject _ChatLogPrefab; //普通
    public GameObject _ChatSysLogPrefab;//系统
    public GameObject _ChatMyLogPrefab; //我的
    public GameObject _ChatBattlePrefab; //战斗
    public GameObject _ChatRedPacketPrefab; //红包
    public GameObject _ChatMyRedPacketPrefab; //红包我的
    public GameObject _ChatVoicePrefab; //语音
    public GameObject _ChatMyVoicePrefab; //语音我的

    public List<ChatInfoLogItem> _ShowingChatLog = new List<ChatInfoLogItem>();

    private bool _IsUpdateNew = true;
    private int _UnReadCount = 0;
    protected int _ShowingHistoryIdxMin = 0;
    protected int _ShowingHistoryIdxMax = 0;
    private float _LastSliderUpdateTime = 0;

    protected int _SelectedCannel = 0;
    protected UInt64 _FriendGuid = GlobeVar.INVALID_GUID;
    public const int _MAX_SHOW_COUNT = 200;
    public const int _SHOW_COUNT_IN_SINGLE_WIN = 20;
    public const float _SLIDER_UPDATE_DELAY = 0.5f;

    public virtual void OnReceiveChat()
    {
        int HistoryCount = GameManager.gameManager.PlayerDataPool.ChatHistory.ChatHistoryList.Count;
        ChatHistoryItem LastHistory = GameManager.gameManager.PlayerDataPool.ChatHistory.ChatHistoryList[HistoryCount - 1];
        if ((int)GC_CHAT.CHATTYPE.CHAT_TYPE_FRIEND == _SelectedCannel
            && (LastHistory.EChannel == GC_CHAT.CHATTYPE.CHAT_TYPE_FRIEND || LastHistory.EChannel == GC_CHAT.CHATTYPE.CHAT_TYPE_TELL))
        {
            if (_FriendGuid == LastHistory.SenderGuid
                || GameManager.gameManager.PlayerDataPool.MainPlayerBaseAttr.Guid == LastHistory.SenderGuid)
            {
                if (!_IsUpdateNew)
                {
                    AddUnReadNew();
                    return;
                }

                if (_ShowingChatLog.Count > _SHOW_COUNT_IN_SINGLE_WIN)
                {
                    RecicleLastOne();
                }
                _ShowingHistoryIdxMax = HistoryCount - 1;
                _LastSliderUpdateTime = Time.time;
                HandleChatHistory(LastHistory);
            }
        }
        else if ((int)LastHistory.EChannel == _SelectedCannel
            || ((LastHistory.EChannel == GC_CHAT.CHATTYPE.CHAT_TYPE_LOUDSPEAKER
                    || LastHistory.EChannel == GC_CHAT.CHATTYPE.CHAT_TYPE_ALLSERSPEAKER
                    || LastHistory.EChannel == GC_CHAT.CHATTYPE.CHAT_TYPE_CROSSSERSPEAKER) 
                && (int)GC_CHAT.CHATTYPE.CHAT_TYPE_WORLD == _SelectedCannel
                && !LastHistory.IsSystem))
        {
            if (!_IsUpdateNew)
            {
                AddUnReadNew();
                return;
            }

            if (_ShowingChatLog.Count > _SHOW_COUNT_IN_SINGLE_WIN)
            {
                RecicleLastOne();
            }
            _ShowingHistoryIdxMax = HistoryCount - 1;
            _LastSliderUpdateTime = Time.time;
            HandleChatHistory(LastHistory);
        }
    }

    public void OnBtnReadNewClick()
    {
        UpdateChannelHistory();
        _ChatLogContent.anchoredPosition = new Vector2(_ChatLogContent.anchoredPosition.x, 0);
    }

    public void OnHistoryContentSlider()
    {
        if (Time.time - _LastSliderUpdateTime < _SLIDER_UPDATE_DELAY)
            return;

        _LastSliderUpdateTime = Time.time;
        LogModule.DebugLog("OnHistoryContentSlider:" + _ChatLogContent.anchoredPosition.y);
        if (_ChatLogContent.anchoredPosition.y >= -20)
        {
            int maxCount = GameManager.gameManager.PlayerDataPool.ChatHistory.ChatHistoryList.Count - 1;
            if (_ShowingHistoryIdxMax <= maxCount)
            {
                if (!_IsUpdateNew)
                {
                    _IsUpdateNew = true;
                    UpdateChannelHistory();
                }
                //_ChatLogContent.anchoredPosition = new Vector2(_ChatLogContent.anchoredPosition.x, 0);
            }
        }
        else if(_ChatSliderRect.sizeDelta.y - _ChatLogContent.anchoredPosition.y > _ChatLogContent.sizeDelta.y)
        {
            if (_ShowingHistoryIdxMin > 1)
            {
                UpdateChannelHistoryRange(_ShowingHistoryIdxMin - 1, true);
            }
            if (_IsUpdateNew)
            {
                _IsUpdateNew = false;
            }
        }
        else
        {
            if (_IsUpdateNew)
            {
                _IsUpdateNew = false;
            }
        }
    }

    public virtual void UpdateChannelHistory()
    {
        ClearHistory();
        ClearUnReanNew();
        int maxCount = GameManager.gameManager.PlayerDataPool.ChatHistory.ChatHistoryList.Count;
        int showedCnt = 0;
        for (int j = maxCount - 1; j >= 0; --j)
        {
            var chatItem = GameManager.gameManager.PlayerDataPool.ChatHistory.ChatHistoryList[j];
            if ((int)chatItem.EChannel == _SelectedCannel)
            {
                try
                {
                    HandleChatHistory(chatItem, false);
                }
                catch (Exception e)
                {
                    LogModule.ErrorLog("chat history error:" + e.ToString());
                }
                if (chatItem.SenderGuid != GlobeVar.INVALID_GUID)
                {
                    showedCnt += 2;
                }
                else
                {
                    ++showedCnt;
                }
            }
            else if (((int)chatItem.EChannel == (int)GC_CHAT.CHATTYPE.CHAT_TYPE_LOUDSPEAKER
                            || (int)chatItem.EChannel == (int)GC_CHAT.CHATTYPE.CHAT_TYPE_ALLSERSPEAKER
                            || (int)chatItem.EChannel == (int)GC_CHAT.CHATTYPE.CHAT_TYPE_CROSSSERSPEAKER) && _SelectedCannel == 5)  //喇叭在世界频道显示
            {
                try
                {
                    HandleChatHistory(chatItem, false);
                }
                catch (Exception e)
                {
                    LogModule.ErrorLog("chat history error:" + e.ToString());
                }
                if (chatItem.SenderGuid != GlobeVar.INVALID_GUID)
                {
                    showedCnt += 2;
                }
                else
                {
                    ++showedCnt;
                }
            }
            if (showedCnt == _SHOW_COUNT_IN_SINGLE_WIN)
            {
                break;
            }
        }

        if (_ShowingChatLog.Count > 0)
        {
            _ShowingHistoryIdxMin = GameManager.gameManager.PlayerDataPool.ChatHistory.ChatHistoryList.IndexOf(_ShowingChatLog[0].ChatHistory);
            _ShowingHistoryIdxMax = GameManager.gameManager.PlayerDataPool.ChatHistory.ChatHistoryList.IndexOf(_ShowingChatLog[_ShowingChatLog.Count - 1].ChatHistory);
        }
    }

    
    public virtual void UpdateChannelHistoryRange(int idxStart, bool isUp)
    {
        int showedCnt = 0;
        if (isUp)
        {
            for (int j = idxStart; j >= 0; --j)
            {
                var chatItem = GameManager.gameManager.PlayerDataPool.ChatHistory.ChatHistoryList[j];
                if ((int)chatItem.EChannel == _SelectedCannel
                    || ((int)chatItem.EChannel == 7 && _SelectedCannel == 5))
                {
                    HandleChatHistory(chatItem, false);
                    _ShowingHistoryIdxMin = j;
                    if (chatItem.SenderGuid != GlobeVar.INVALID_GUID)
                    {
                        showedCnt += 2;
                    }
                    else
                    {
                        ++showedCnt;
                    }
                }

                if (showedCnt == _SHOW_COUNT_IN_SINGLE_WIN * 0.5f)
                {
                    break;
                }
            }   
        }
    }

    public void TestChat()
    {
        int times = 100;
        for (int i = 0; i < times; ++i)
        {
            ChatHistoryItem item = new ChatHistoryItem();
            item.CleanUp();
            item.EChannel = (GC_CHAT.CHATTYPE.CHAT_TYPE_GUILD);
            item.ReceiverGuid = GlobeVar.INVALID_GUID;
            item.ReceiverName = "";

            string modifyText = i.ToString();
            modifyText = Utils.StrFilter_Chat(modifyText);
            item.ChatInfo = modifyText;

            Utils.SendCGChatPak(item.ChatInfo, item);
        }
    }

    protected virtual void HandleChatHistory(ChatHistoryItem history, bool showLast = true)
    {
        ChatInfoLogItem chatLogInfo = null;
        if (history._RedPacketID >= 0 && history.SenderGuid == GameManager.gameManager.PlayerDataPool.MainPlayerBaseAttr.Guid)
        {
            chatLogInfo = GetIdleChatLogItem(_ChatMyRedPacketPrefab);
        }
        else if (history._RedPacketID >= 0 && history.SenderGuid != GameManager.gameManager.PlayerDataPool.MainPlayerBaseAttr.Guid)
        {
            chatLogInfo = GetIdleChatLogItem(_ChatRedPacketPrefab);
        }
        else if (history.EChannel == GC_CHAT.CHATTYPE.CHAT_TYPE_SYSTEM)
        {
            chatLogInfo = GetIdleChatLogItem(_ChatSysLogPrefab);
        }
        else if (history.EChannel == GC_CHAT.CHATTYPE.CHAT_TYPE_BATTLE)
        {
            chatLogInfo = GetIdleChatLogItem(_ChatBattlePrefab);
        }
        else if (history.EChannel == GC_CHAT.CHATTYPE.CHAT_TYPE_GUILD && (history.IsSystem || history.SenderGuid == GlobeVar.INVALID_GUID))
        {
            chatLogInfo = GetIdleChatLogItem(_ChatSysLogPrefab);
        }
        else if ((history.EChannel == GC_CHAT.CHATTYPE.CHAT_TYPE_TEAM
            || history.EChannel == GC_CHAT.CHATTYPE.CHAT_TYPE_LOUDSPEAKER
            || history.EChannel == GC_CHAT.CHATTYPE.CHAT_TYPE_ALLSERSPEAKER
            || history.EChannel == GC_CHAT.CHATTYPE.CHAT_TYPE_CROSSSERSPEAKER) && history.IsSystem)
        {
            chatLogInfo = GetIdleChatLogItem(_ChatSysLogPrefab);
        }
        else if (history.ChatInfo.StartsWith(ChatVoiceInputLogic._VoiceChatStart) && history.SenderGuid == GameManager.gameManager.PlayerDataPool.MainPlayerBaseAttr.Guid)
        {
            chatLogInfo = GetIdleChatLogItem(_ChatMyVoicePrefab);
        }
        else if (history.ChatInfo.StartsWith(ChatVoiceInputLogic._VoiceChatStart) && history.SenderGuid != GameManager.gameManager.PlayerDataPool.MainPlayerBaseAttr.Guid)
        {
            chatLogInfo = GetIdleChatLogItem(_ChatVoicePrefab);
        }
        else
        {
            if (history.SenderGuid == GameManager.gameManager.PlayerDataPool.MainPlayerBaseAttr.Guid)
            {
                chatLogInfo = GetIdleChatLogItem(_ChatMyLogPrefab);
            }
            else
            {
                chatLogInfo = GetIdleChatLogItem(_ChatLogPrefab);
            }
        }

        chatLogInfo.SetChatLog(history);

        if (showLast)
        {
            chatLogInfo.RectTransform.SetAsLastSibling();
            _ShowingChatLog.Add(chatLogInfo);
        }
        else
        {
            chatLogInfo.RectTransform.SetAsFirstSibling();
            _ShowingChatLog.Insert(0, chatLogInfo);
        }

    }

    protected ChatInfoLogItem GetIdleChatLogItem(GameObject prefab)
    {
        GameObject chatLogItemGO = null;
        var chatLogInfo = ResourcePool.Instance.GetIdleUIItem<ChatInfoLogItem>(prefab);
        if (chatLogInfo == null)
        {
            chatLogItemGO = GameObject.Instantiate(prefab) as GameObject;
            chatLogItemGO.name = prefab.name;
            chatLogInfo = chatLogItemGO.GetComponent<ChatInfoLogItem>();
        }
        else
        {
            chatLogItemGO = chatLogInfo.gameObject;
        }

        chatLogItemGO.transform.SetParent(_ChatLogContent);
        chatLogItemGO.transform.localScale = Vector3.one;
        chatLogInfo.RectTransform.sizeDelta = new Vector2(Math.Abs(_ChatLogContent.rect.width), chatLogInfo.RectTransform.rect.height);
        chatLogItemGO.SetActive(true);

        return chatLogInfo;
    }

    protected void RecicleChatLogItem(ChatInfoLogItem chatItem)
    {
        chatItem.gameObject.SetActive(false);
        ResourcePool.Instance.RecvIldeUIItemImmediately(chatItem.gameObject);
        //chatItem.transform.SetParent(null);
        //chatItem.gameObject.SetActive(false);
        //if (!_IdleChatItems.ContainsKey(chatItem.name))
        //{
        //    _IdleChatItems.Add(chatItem.name, new Stack<ChatInfoLogItem>());
        //}
        //_IdleChatItems[chatItem.name].Push(chatItem);
       
    }

    void RecicleLastOne()
    {
        RecicleChatLogItem(_ShowingChatLog[0]);
        _ShowingChatLog.RemoveAt(0);

        _ShowingHistoryIdxMin = GameManager.gameManager.PlayerDataPool.ChatHistory.ChatHistoryList.IndexOf(_ShowingChatLog[0].ChatHistory);
    }

    void RecicleRange(int idxMin, int idxMax)
    {
        List<ChatInfoLogItem> recicleRange = new List<ChatInfoLogItem>();
        float deltaHeight = 0;
        for (int i = idxMin; i < idxMax; ++i)
        {
            if (i >= 0 && i < _ShowingChatLog.Count)
            {
                RecicleChatLogItem(_ShowingChatLog[i]);
                deltaHeight += _ShowingChatLog[i].GetItemHeight();
            }
        }
        _ShowingChatLog.RemoveRange(idxMin, idxMax - idxMin);

        _ShowingHistoryIdxMin = GameManager.gameManager.PlayerDataPool.ChatHistory.ChatHistoryList.IndexOf(_ShowingChatLog[0].ChatHistory);
        _ShowingHistoryIdxMax = GameManager.gameManager.PlayerDataPool.ChatHistory.ChatHistoryList.IndexOf(_ShowingChatLog[_ShowingChatLog.Count - 1].ChatHistory);
    }

    void AddUnReadNew()
    {
        ++_UnReadCount;
        _NewLogGO.SetActive(true);
        _NewLogTip.text = StrDictionary.GetClientDictionaryString("#{4901}", _UnReadCount);
    }

    protected void ClearUnReanNew()
    {
        _UnReadCount = 0;
        _NewLogGO.SetActive(false);
    }

    public virtual void ClearHistory()
    {
        _ChatLogContent.sizeDelta = new Vector2(_ChatLogContent.sizeDelta.x, 0);
        _UnReadCount = 0;
        _IsUpdateNew = true;

        var historyClear = _ChatLogContent.GetComponentsInChildren<ChatInfoLogItem>();
        foreach (var chatItem in historyClear)
        {
            RecicleChatLogItem(chatItem);
        }
        _ShowingChatLog.Clear();
    }

    #endregion

    #region voice
    public void UpdateVoiceAnim()
    {
        Debug.Log("_ShowingChatLog:" + _ShowingChatLog.Count);
        foreach (var chatItem in _ShowingChatLog)
        {
            if (chatItem is ChatInfoLogItemVoice)
            {
                ChatInfoLogItemVoice chatVoiceItem = chatItem as ChatInfoLogItemVoice;
                if (chatVoiceItem == null)
                    continue;

                if (chatItem.ChatHistory == ChatVoice.Instance().GetPlayingChat())
                {
                    chatVoiceItem.PlayVoiceAnim();
                }
                else
                {
                    chatVoiceItem.StopVoiceAnim();
                }
            }
        }
    }

    #endregion

}