using ESBasic;
using ESBasic.ObjectManagement.Managers;
using Newtonsoft.Json;
using OMCS;
using OMCS.Boost;
using OMCS.Boost.Forms;
using OMCS.Passive;
using OMCS.Passive.Audio;
using OMCS.Passive.MultiChat;
using Oraycn.MCapture;
using Oraycn.MFile;
using OVCS.ClientWinform;
using OVCS.Core;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows.Forms;

namespace OVCS
{
    public delegate TabPage CbCreateTabpage(string userID);
    public partial class MainForm : Form
    {
        private IMultimediaManager multimediaManager = null;
        private string currentUserID;
        private string roomID;
        private int messageCount = 0;
        private bool currentPageIsIM = false;
        private bool shareDesk = false;
        private ObjectManager<string, TabPage> outTabPages = new ObjectManager<string, TabPage>();
        private System.Threading.Timer timer;
        JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings();
        private TextChatControl textChatControl1;
        private GroupExtension groupExtension;
        private IChatGroup chatGroup;
        public MainForm()
        {
            InitializeComponent();
            jsonSerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
            this.StartPosition = FormStartPosition.CenterScreen;
            this.textChatControl1 = new TextChatControl();
            this.textChatControl1.Dock = DockStyle.Fill;
            this.tabPage2.Controls.Add(this.textChatControl1);
            this.AcceptButton = this.textChatControl1.ButtonSend;
        }
        /// <summary>
        /// 获取扩展信息 
        /// </summary>
        private void GetGroupExtension()
        {
            this.multimediaManager.SendCustomizedMessage(null, InformationTypes.GetGroupExtension, null, this.roomID);
        }

        private void HandleGroupExtension(GroupExtension groupExtension)
        {
            this.groupExtension = groupExtension;
            if (this.groupExtension.DesktopSharedUserID != null)
            {
                this.OpenRemotingDesktop(this.groupExtension.DesktopSharedUserID);
            }
        }

        #region Initialize
        public void Initialize(IMultimediaManager _multimediaManager, string userID, string _roomID)
        {
            this.Cursor = Cursors.WaitCursor;
            this.multimediaManager = _multimediaManager;
            this.currentUserID = userID;
            this.roomID = _roomID;
            MultimediaManagerHelper.WaitUtilAvailable(this.multimediaManager, 30);

            this.Text += " - 房间：" + this.roomID;
            this.toolStripLabel_User.Text = "当前登录:" + this.currentUserID;

            this.textChatControl1.Initialize(this.currentUserID, this.roomID, _multimediaManager);

            this.whiteBoardConnector1.AutoReconnect = false;
            this.whiteBoardConnector1.ConnectEnded += new ESBasic.CbGeneric<string, OMCS.Passive.ConnectResult>(whiteBoardConnector1_ConnectEnded);

            this.multimediaManager.ConnectionInterrupted += new CbGeneric<IPEndPoint>(multimediaManager_ConnectionInterrupted);
            this.multimediaManager.CustomizedMessageReceived += MultimediaManager_CustomizedMessageReceived;
            this.chatGroup = this.multimediaManager.ChatGroupEntrance.Join(OMCS.Contracts.ChatType.Video, this.roomID);
            this.GetGroupExtension();
            this.chatGroup.SomeoneJoin += ChatGroup_SomeoneJoin;
            this.chatGroup.SomeoneExit += ChatGroup_SomeoneExit;
            this.multiVideoChatContainer1.Initialize(this.multimediaManager, this.roomID);

            this.whiteBoardConnector1.BeginConnect(this.roomID);
            this.timer = new System.Threading.Timer(new System.Threading.TimerCallback(this.TimerAction), null, 1000, 1000);
        }


        private void TimerAction(object state)
        {
            if (this.gotoClose)
            {
                return;
            }

            if (this.InvokeRequired)
            {
                this.BeginInvoke(new CbGeneric<object>(this.TimerAction), state);
            }
            else
            {
                if (this.isRecording)
                {
                    TimeSpan ts = new TimeSpan(0, 0, ++this.recordSeconds);
                    this.toolStripLabel_record.Text = ts.Hours.ToString("00") + ":" + ts.Minutes.ToString("00") + ":" + ts.Seconds.ToString("00");
                }
            }
        }

        #region 连接断开 

        void multimediaManager_ConnectionInterrupted(IPEndPoint ipe)
        {
            if (this.gotoClose)
            {
                return;
            }

            if (this.InvokeRequired)
            {
                this.BeginInvoke(new CbGeneric<IPEndPoint>(this.multimediaManager_ConnectionInterrupted), ipe);
            }
            else
            {
                if (this.gotoClose)
                {
                    return;
                }
                MessageBox.Show("您已经掉线！");
                this.gotoClose = true;
                this.Close();
            }
        }
        #endregion

        #region 被挤掉线
        void BasicOutter_BeingPushedOut()
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new CbGeneric(this.BasicOutter_BeingPushedOut));
            }
            else
            {
                if (this.gotoClose)
                {
                    return;
                }
                MessageBox.Show("已经在其它地方登录！");
                this.gotoClose = true;
                this.Close();
            }
        }
        #endregion
        #endregion

        #region ChatGroup_SomeoneExit 、ChatGroup_SomeoneJoin       

        private void ChatGroup_SomeoneExit(string memberID)
        {   //如果有远程 连接到该组员，断开远程连接
            this.CloseRemotingDesktop(memberID, false);
            this.ShowSystemMessage(memberID + "掉线！");
        }

        private void ChatGroup_SomeoneJoin(IChatUnit unit)
        {
            this.ShowSystemMessage(unit.MemberID + "上线！");

            //如果自己有共享 桌面给 组友，那么就给该新加入的组友一条 共享 其桌面的消息 ，并在授权列表中添加该组员
            //if (this.shareDesk)
            //{
            //    this.rapidPassiveEngine.CustomizeOutter.Send(memberID, InformationTypes.ShareDesk, null, true, ActionTypeOnChannelIsBusy.Continue);
            //}
        }

        #endregion

        #region MultimediaManager_CustomizedMessageReceived  

        /// <summary>
        /// 当收到来自服务器或其它客户端的自定义消息时触发
        /// </summary>
        /// <param name="destID">用户ID</param>
        /// <param name="chatType">消息类型</param>
        /// <param name="data">数据</param>
        /// <param name="tag">额外信息</param>
        private void MultimediaManager_CustomizedMessageReceived(string destID, int chatType, byte[] data, string tag)
        {
            try
            {
                string[] strings = tag.Split('-');
                if (strings[0] == this.roomID)
                {
                    #region 即时通信消息的处理
                    if (chatType == InformationTypes.BroadcastChat)
                    {
                        string content = Encoding.UTF8.GetString(data);

                        ChatMessageRecord record = JsonConvert.DeserializeObject<ChatMessageRecord>(content, this.jsonSerializerSettings);
                        string contentEmoji = ParseEmotionRichText(record.ContentStr);
                        string msg = string.Format("{0}说: ", record.SpeakerID, DateTime.Now) + contentEmoji;
                        //当收到广播 消息，如果tablePage不在即时通讯 页，则在 标题上面显示 新增 消息数量
                        this.DealBeforeShowMessage(msg);
                        if (record != null)
                        {
                            this.textChatControl1.ShowOtherTextChat(record.SpeakerID, record);
                        }
                        return;
                    }
                    #endregion

                    #region 共享桌面消息的处理
                    if (chatType == InformationTypes.BroadcastShareDesk)
                    {
                        bool isShare = BitConverter.ToBoolean(data, 0);
                        if (isShare)
                        {
                            this.OpenRemotingDesktop(strings[1]);
                        }
                        else
                        {
                            this.CloseRemotingDesktop(strings[1], true);
                        }
                        return;
                    }
                    #endregion

                    #region 群组扩展信息

                    if (chatType == InformationTypes.GetGroupExtension)
                    {
                        string cont = Encoding.UTF8.GetString(data);
                        GroupExtension extension = JsonConvert.DeserializeObject<GroupExtension>(cont);
                        this.HandleGroupExtension(extension);
                    }

                    #endregion

                    #region 控制是否能 控制远程桌面

                    if (chatType == InformationTypes.ControlDesktop)
                    {
                        this.CustomizeHandler_ControlRemotingDesktop(strings[1], BitConverter.ToBoolean(data, 0));
                        return;
                    }

                    #endregion

                    #region 收到共享 桌面的消息 

                    if (chatType == InformationTypes.ShareDesk)
                    {
                        this.OpenRemotingDesktop(strings[1]);
                        return;
                    }

                    #endregion

                    #region 客户端的摄像头索引发生变化
                    if (chatType == InformationTypes.CameraIndexChanged)
                    { 
                        this.CameraIndexChange(strings[1]);
                    }
                    #endregion
                }
            }
            catch (Exception ee)
            {
                Program.Logger.Log(ee, "mainform.GroupOutter_BroadcastReceived", ESBasic.Loggers.ErrorLevel.High);
                MessageBox.Show(ee.Message);
            }
        }

        #endregion

        #region CameraIndexChange

        private void CameraIndexChange(string destID)
        {
            this.multiVideoChatContainer1.CameraIndexChange(destID);
        }
        #endregion

        #region CustomizeHandler_ControlRemotingDesktop
        public void CustomizeHandler_ControlRemotingDesktop(string userID, bool canControl)
        {
            TabPage page = this.GetDesktopPanelPage(userID);
            if (page == null)
            {
                page = this.outTabPages.Get(userID);
            }

            (page.Controls[0] as RemoteDesktopPanel).Control(canControl);

        }
        #endregion

        #region whiteBoardConnector1_ConnectEnded
        void whiteBoardConnector1_ConnectEnded(string ownerId, OMCS.Passive.ConnectResult result)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new CbGeneric<string, ConnectResult>(this.whiteBoardConnector1_ConnectEnded), ownerId, result);
            }
            else
            {
                this.toolStripButton_record.Visible = true;
                this.Cursor = Cursors.Default;
                if (result != ConnectResult.Succeed)
                {
                    this.ShowSystemMessage(string.Format("电子白板连接失败！{0}", result.ToString()));
                }
            }
        }
        #endregion

        #region tabControl1_SelectedIndexChanged
        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.tabControl1.SelectedIndex == 1)
            {
                this.currentPageIsIM = true;
                this.messageCount = 0;
                this.ChangePageText();
            }
            else
            {
                this.currentPageIsIM = false;

            }
        }
        #endregion

        #region 即时消息
        #region ChangePageText
        void ChangePageText()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new CbGeneric(this.ChangePageText));
            }
            else
            {
                if (this.messageCount == 0)
                {
                    this.tabPage2.Text = "即时消息";
                }
                else
                {
                    this.tabPage2.Text = string.Format("即时消息(+{0})", this.messageCount);
                }
            }
        }
        #endregion 
        #endregion

        #region 远程桌面
        #region OpenRemotingDesktop
        public void OpenRemotingDesktop(string broadcasterID)
        {
            this.ShowSystemMessage(broadcasterID + "开启了桌面共享！");

            TabPage page = this.GetDesktopPanelPage(broadcasterID);
            this.groupExtension.DesktopSharedUserID = broadcasterID;
            if (page == null)
            {
                //新 生成一个page，且选中，远程连接到广播者 的桌面 
                this.CreateDesktopPage(broadcasterID);
            }
        }
        #endregion
        #region CloseRemotingDesktop//断开远程桌面的连接，关闭page
        private void CloseRemotingDesktop(string userID, bool showMessage)
        {
            if (showMessage)
            {
                this.ShowSystemMessage(userID + "关闭了桌面共享！");
            }
            this.groupExtension.DesktopSharedUserID = null;
            TabPage page = this.GetDesktopPanelPage(userID);
            if (page != null)
            {
                this.CloseShowInTabPage(page);
            }
            else
            {
                page = this.outTabPages.Get(userID);
                if (page != null)
                {
                    this.CloseOutShowTabPage(page);
                }
            }
        }
        #endregion
        #region CloseAllRemotingDesktop//断开所有远程桌面的连接，关闭page
        private void CloseAllRemotingDesktop()
        {
            for (int i = this.tabControl1.TabPages.Count - 1; i >= 3; i--)
            {
                this.CloseShowInTabPage(this.tabControl1.TabPages[i]);
            }
            foreach (TabPage page in this.outTabPages.GetAll())
            {
                this.CloseOutShowTabPage(page);
            }

        }
        #endregion
        #region CloseShowInTabPage
        private void CloseShowInTabPage(TabPage page)
        {
            RemoteDesktopPanel desktopPanel = page.Controls[0] as RemoteDesktopPanel;
            if (desktopPanel != null)
            {
                desktopPanel.DisConnect();
                this.ClosePage(page);
            }
        }
        #endregion
        #region CloseOutShowTabPage
        private void CloseOutShowTabPage(TabPage page)
        {
            RemoteDesktopPanel desktopPanel = page.Controls[0] as RemoteDesktopPanel;
            desktopPanel.DisConnect();
            desktopPanel.CloseShowFormDirectly = true;
            desktopPanel.ShowForm.CloseForm();
            this.outTabPages.Remove(page.Name);
        }
        #endregion


        #region CreateDesktopPage
        private void CreateDesktopPage(string broadcasterID)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new CbGeneric<string>(this.CreateDesktopPage), broadcasterID);
            }
            else
            {
                TabPage page = new TabPage();
                page.Text = broadcasterID + "的桌面";
                page.Name = broadcasterID;
                page.ImageIndex = 2;
                RemoteDesktopPanel desktopPanel = new RemoteDesktopPanel();
                desktopPanel.Initialize(page);
                desktopPanel.HidePageEvent += new CbGeneric<TabPage>(desktopPanel_HidePageEvent);
                desktopPanel.ShowPageEvent += new CbGeneric<string>(desktopPanel_ShowPageEvent);
                desktopPanel.Dock = DockStyle.Fill;

                page.Controls.Add(desktopPanel);
                this.tabControl1.TabPages.Add(page);
                this.tabControl1.SelectedIndex = this.tabControl1.TabPages.Count - 1;
                desktopPanel.Connect(broadcasterID);
            }

        }

        void desktopPanel_ShowPageEvent(string pageName)
        {
            TabPage page = this.outTabPages.Get(pageName);
            this.tabControl1.TabPages.Add(page);
            this.tabControl1.SelectedIndex = this.tabControl1.TabPages.Count - 1;
            this.outTabPages.Remove(pageName);
        }


        void desktopPanel_HidePageEvent(TabPage page)
        {
            this.outTabPages.Add(page.Name, page);
            this.tabControl1.TabPages.Remove(page);
        }

        #endregion
        #region GetDesktopPanelPage
        private TabPage GetDesktopPanelPage(string broadcasterID)
        {
            for (int i = 2; i < this.tabControl1.TabPages.Count; i++)
            {
                if (this.tabControl1.TabPages[i].Name == broadcasterID)
                {
                    return this.tabControl1.TabPages[i];
                }
            }
            return null;
        }
        #endregion

        #region ClosePage
        private void ClosePage(TabPage page)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new CbGeneric<TabPage>(this.ClosePage), page);
            }
            else
            {
                this.tabControl1.TabPages.Remove(page);
                this.tabControl1.SelectedIndex = 0;
            }
        }
        #endregion

        #endregion

        #region MainForm_FormClosing
        private bool gotoClose = false;
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.gotoClose = true;
            this.multiVideoChatContainer1.Close();
            this.multimediaManager.DisconnectGuest(false);
            this.multimediaManager.Dispose();
        }
        #endregion 

        private void ShowSystemMessage(string message)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new CbGeneric<string>(this.ShowSystemMessage), message);
            }
            else
            {
                this.DealBeforeShowMessage(message);
                this.textChatControl1.ShowSystemMessage(message);
                this.ShowBallonForm(message);
            }
        }
        private void ShowBallonForm(string message)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new CbGeneric<string>(this.ShowBallonForm), message);
            }
            else
            {
                BallonForm ballonForm = new BallonForm();
                ballonForm.ScrollShow(message);
            }
        }
        #region DealBeforeShowMessage
        private void DealBeforeShowMessage(string msg)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new CbGeneric<string>(this.DealBeforeShowMessage), msg);
            }
            else
            {
                if (msg.Length > 40)
                {
                    msg = msg.Substring(0, 40) + "......";
                }
                this.toolStripLabel_lastMessage.Text = msg;
                if (!this.currentPageIsIM)
                {
                    this.messageCount++;
                    this.ChangePageText();
                }
            }
        }
        #endregion

        #region 共享桌面
        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            try
            {
                this.shareDesk = this.checkBox1.Checked;
                if (this.shareDesk)
                {
                    if (this.groupExtension.DesktopSharedUserID != null)
                    {
                        MessageBox.Show(string.Format("{0}正在共享桌面", this.groupExtension.DesktopSharedUserID), "ERROR");
                        this.checkBox1.Checked = false;
                        return;
                    }
                    this.授权ToolStripMenuItem.Visible = true;
                    this.groupExtension.DesktopSharedUserID = this.currentUserID;
                    List<IChatUnit> chatUnits = this.chatGroup.GetOtherMembers();
                    foreach (IChatUnit chatUnit in chatUnits)
                    {
                        ToolStripMenuItem item = new ToolStripMenuItem(chatUnit.MemberID);
                        this.授权ToolStripMenuItem.DropDownItems.Add(item);
                        item.Click += new EventHandler(item_Click);
                    }
                }
                else
                {
                    if (this.groupExtension.DesktopSharedUserID != this.currentUserID)
                    {
                        return;
                    }
                    this.授权ToolStripMenuItem.Visible = false;
                    this.groupExtension.DesktopSharedUserID = null;
                    this.授权ToolStripMenuItem.DropDownItems.Clear();
                }

                this.multimediaManager.SendCustomizedMessage(null, InformationTypes.BroadcastShareDesk, BitConverter.GetBytes(this.shareDesk), this.roomID);
            }
            catch (Exception ee)
            {
                Program.Logger.Log(ee, "MainForm.checkBox1_CheckedChanged", ESBasic.Loggers.ErrorLevel.High);
                MessageBox.Show(ee.Message);
            }
        }

        void item_Click(object sender, EventArgs e)
        {
            try
            {
                ToolStripMenuItem currentItem = (sender as ToolStripMenuItem);
                currentItem.Checked = !currentItem.Checked;
                string tag = string.Format("{0}-{1}", this.roomID, currentItem.Text);
                this.multimediaManager.SendCustomizedMessage(null, InformationTypes.ControlDesktop, BitConverter.GetBytes(currentItem.Checked), tag);
                //如果是授权给某人，那么要去掉其他人的受控权
                if (currentItem.Checked)
                {
                    for (int i = 0;i < this.授权ToolStripMenuItem.DropDownItems.Count; i++)
                    {
                        ToolStripMenuItem item = this.授权ToolStripMenuItem.DropDownItems[i] as ToolStripMenuItem;
                        if (item != null && item.Text != currentItem.Text && item.Checked)
                        {
                            item.Checked = false;
                            string _tag = string.Format("{0}-{1}", this.roomID, item.Text);
                            this.multimediaManager.SendCustomizedMessage(null, InformationTypes.ControlDesktop, BitConverter.GetBytes(false), _tag);
                        }
                    }
                }
            }
            catch (Exception ee)
            {
                Program.Logger.Log(ee, "mainform.item_Click", ESBasic.Loggers.ErrorLevel.High);
                MessageBox.Show(ee.Message);
            }

        }
        #endregion

        private void 设备测试ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DeviceSelectForm form = new DeviceSelectForm();
            form.ShowDialog();
        }

        #region 录制2020.03.06
        private IDesktopCapturer desktopCapturer;
        private VideoFileMaker videoFileMaker;
        private AudioInOutMixer audioInOutMixer;
        private int recordSeconds = 0;
        private bool isRecording = false;
        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            if (!this.isRecording)
            {
                this.StartRecord();
                this.isRecording = true;
                this.toolStripButton_record.Text = "停止录制";
                this.recordSeconds = 0;
                this.toolStripLabel_record.Visible = true;
            }
            else
            {
                this.isRecording = false;
                this.StopRecord();
                this.toolStripButton_record.Text = "开始录制";
                this.toolStripLabel_record.Visible = false;
                this.recordSeconds = 0;
                MessageBox.Show("录制完成！");
            }
            this.Cursor = Cursors.Default;
        }

        private void StartRecord()
        {
            Rectangle region = this.Bounds;
            region = new Rectangle(region.Location, new Size(region.Width / 8 * 8, region.Height / 8 * 8)); //宽和高规整为8的倍数
            int fps = 10;
            this.desktopCapturer = CapturerFactory.CreateDesktopCapturer(fps, false, region);
            this.desktopCapturer.ImageCaptured += this.Form1_ImageCaptured;

            this.audioInOutMixer = new AudioInOutMixer();
            this.audioInOutMixer.Initialize(this.multimediaManager);
            this.audioInOutMixer.AudioMixed += AudioInOutMixer_AudioMixed;

            this.videoFileMaker = new VideoFileMaker();
            this.videoFileMaker.Initialize("test.mp4", Oraycn.MFile.VideoCodecType.H264, region.Width, region.Height, fps, VideoQuality.High, Oraycn.MFile.AudioCodecType.AAC, 16000, 1, true);

            this.desktopCapturer.Start();
        }

        private void AudioInOutMixer_AudioMixed(byte[] audioData)
        {
            if (this.isRecording)
            {
                this.videoFileMaker.AddAudioFrame(audioData);
            }
        }

        private void StopRecord()
        {
            this.desktopCapturer.Stop();
            this.audioInOutMixer.Dispose();
            this.videoFileMaker.Close(true);
        }

        private int imageCount = 0;
        //采集到的桌面图像
        void Form1_ImageCaptured(Bitmap img)
        {
            if (this.isRecording)
            {
                this.videoFileMaker.AddVideoFrame(img);
            }
        }
        #endregion


        /// <summary>
        /// 将文字和表情解析后显示到会话中
        /// </summary>
        /// <param name="richText"></param>
        /// <returns></returns>
        public string ParseEmotionRichText(string richText)
        {
            if (richText.Contains('[') && richText.Contains(']'))
            {
                Dictionary<uint, uint> emotionDic_temp = new Dictionary<uint, uint>();
                for (int i = richText.Length - 1; i >= 0; i--)
                {
                    if (richText[i] == '[' && i + 4 < richText.Length)
                    {
                        if (richText[i + 4] == ']')
                        {
                            int emotionIndex = -1;
                            int.TryParse(richText.Substring(i + 1, 3), out emotionIndex);
                            if (emotionIndex > -1)//中间是表情
                            {
                                emotionDic_temp.Add((uint)i, (uint)emotionIndex);
                                richText = richText.Remove(i, 5);
                                richText = richText.Insert(i, "[表情]");
                            }
                        }
                    }
                }
            }
            return richText;
        }

        private void pictureBox_Setting_Click(object sender, EventArgs e)
        { 
            SettingForm setttingForm = new SettingForm(); 
            setttingForm.Show();
        }

        #region SendCameraIndexChange

        internal void SendCameraIndexChange()
        {
            if (this.multiVideoChatContainer1.myselfPanel.CameraConnectResult != ConnectResult.Succeed)
            {
                this.multimediaManager.SendCustomizedMessage(null, InformationTypes.CameraIndexChanged, null, roomID);
                this.CameraIndexChange(this.multimediaManager.CurrentUserID);
            }
        }

        #endregion
    }
}
