//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
using System;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Windows.Forms;
using Revisor.VMS.ClientSDK;
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
namespace ViewRealtimeExample
{
    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
    public partial class TestForm : Form
    {
        //----------------------------------------------------------------------------------------------------------------------------------------------------------------
        #region Properties

        private ConnectionStatus _status;
        private ConnectionWrapper _connection;
        private RecordHelper _recordHelper;

        private enum ConnectionStatus
        {
            Disconnected,
            Connecting,
            Connected
        }

        #endregion
        //----------------------------------------------------------------------------------------------------------------------------------------------------------------
        #region Methods

        /// <summary>
        /// Creates an instance of the TestForm class.
        /// </summary>
        public TestForm()
        {
            InitializeComponent();
            SetStatus(ConnectionStatus.Disconnected);
        }

        private async void StartConnect(string serverName, string user, string password)
        {
            SetStatus(ConnectionStatus.Connecting);

            try
            {
                _connection = new ConnectionWrapper();
                await _connection.ConnectAsync(serverName, 11012, user, password);
                FinishConnect(null);
            }
            catch (Exception ex)
            {
                FinishConnect(ex);
            }
        }

        private void FinishConnect(Exception ex)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<Exception>(FinishConnect), ex);
                return;
            }

            if (_connection != null && _connection.Connected)
            {
                SetStatus(ConnectionStatus.Connected);
                InitiatePlayback();
            }
            else
            {
                CancelConnect();

                if (ex != null)
                {
                    MessageBox.Show("ERROR: " + GetFullExceptionText(ex));
                }
            }
        }

        private void InitiatePlayback()
        {
            if (_connection != null)
            {
                var configuration = _connection.GetConfiguration();
                var cameras = configuration.Cameras;
                var camera = cameras.Find(c => !c.Disabled);

                videoControl.Play(camera, 30);
            }
        }

        private void CancelConnect()
        {
            videoControl.Stop();

            if (_connection != null)
            {
                _connection.Dispose();
                _connection = null;
            }

            SetStatus(ConnectionStatus.Disconnected);
        }

        private void SetStatus(ConnectionStatus status)
        {
            _status = status;

            labelStatus.Text = _status.ToString();
            textServer.Enabled = textUser.Enabled = textPassword.Enabled = (_status == ConnectionStatus.Disconnected);

            buttonConnect.Text = (_status == ConnectionStatus.Disconnected
                ? "Connect"
                : "Disconnect"
            );

            buttonStreamAuto.Enabled = (_status == ConnectionStatus.Connected);
            buttonFreeze.Enabled = (_status == ConnectionStatus.Connected);
            buttonAudio.Enabled = (_status == ConnectionStatus.Connected);
            buttonSnapshot.Enabled = (_status == ConnectionStatus.Connected);
            buttonRecord.Enabled = (_status == ConnectionStatus.Connected);

            if (_status != ConnectionStatus.Connected)
            {
                buttonFreeze.Checked = false;
                buttonAudio.Checked = false;
                buttonRecord.Checked = false;

                StartOrStopRecord(false);
            }
        }

        private string GetFullExceptionText(Exception ex)
        {
            var result = ex.Message;
            var innerEx = ex.InnerException;

            while (innerEx != null)
            {
                result += Environment.NewLine + innerEx.Message;
                innerEx = innerEx.InnerException;
            }

            return result;
        }

        private void StartOrStopRecord(bool enable)
        {
            if (enable && _recordHelper == null)
            {
                _recordHelper = new RecordHelper(videoControl);
            }
            else if (!enable && _recordHelper != null)
            {
                var fileName = _recordHelper.FileName;
                var exception = _recordHelper.GetErrorIfOccured();

                if (exception != null)
                {
                    MessageBox.Show("Recording saved with errors. File name: " 
                        + fileName 
                        + Environment.NewLine
                        + "Error: " 
                        + exception.Message
                    );
                }
                else
                {
                    MessageBox.Show("Recording saved to: " + _recordHelper.FileName);
                }

                _recordHelper.Dispose();
                _recordHelper = null;
            }

            buttonRecord.Checked = enable;
        }

        private void buttonConnect_Click(object sender, EventArgs e)
        {
            if (_status == ConnectionStatus.Disconnected)
            {
                StartConnect(textServer.Text, textUser.Text, textPassword.Text);
            }
            else
            {
                CancelConnect();
            }
        }

        private void buttonFreeze_Click(object sender, EventArgs e)
        {
            videoControl.IsFreezed = buttonFreeze.Checked;
        }

        private void buttonAudio_Click(object sender, EventArgs e)
        {
            videoControl.PlayAudio = buttonAudio.Checked;
        }

        private void buttonSnapshot_Click(object sender, EventArgs e)
        {
            try
            {
                using (var bitmap = videoControl.GetCurrentImageCopy())
                {
                    if (bitmap == null)
                    {
                        MessageBox.Show("Image is missing");
                        return;
                    }

                    var fileName = Path.Combine(
                        Directory.GetCurrentDirectory(),
                        string.Format("{0}.jpeg",
                            DateTime.Now.ToString("yyyy_MM_dd-HH-mm-ss", CultureInfo.InvariantCulture))
                    );

                    bitmap.Save(fileName, ImageFormat.Jpeg);

                    MessageBox.Show("Saved to " + fileName);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("ERROR: " + GetFullExceptionText(ex));
            }
        }

        private void buttonStreamAuto_Click(object sender, EventArgs e)
        {
            videoControl.SourceType = VideoSourceType.Auto;
            buttonStreamAuto.Checked = true;
            buttonStreamFirst.Checked = false;
            buttonStreamSecond.Checked = false;
        }

        private void buttonStreamFirst_Click(object sender, EventArgs e)
        {
            videoControl.SourceType = VideoSourceType.Main;
            buttonStreamAuto.Checked = false;
            buttonStreamFirst.Checked = true;
            buttonStreamSecond.Checked = false;
        }

        private void buttonStreamSecond_Click(object sender, EventArgs e)
        {
            videoControl.SourceType = VideoSourceType.Second;
            buttonStreamAuto.Checked = false;
            buttonStreamFirst.Checked = false;
            buttonStreamSecond.Checked = true;
        }

        private void buttonRecord_Click(object sender, EventArgs e)
        {
            StartOrStopRecord(!buttonRecord.Checked);
        }

        private void TestForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            StartOrStopRecord(false);
            CancelConnect();
        }

        #endregion
        //----------------------------------------------------------------------------------------------------------------------------------------------------------------
    }
    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
