/******************************************************************************/
/*                                                                            */
/* Copyright Avaya LLC.                                                       */
/*                                                                            */
/******************************************************************************/
using Avaya.ClientServices;
using Avaya.ClientServices.Media;
using SampleConferenceApp.SDK;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Web;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;

namespace SampleConferenceApp
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public static char Dtmf = ' ';
        public static String OldDtmfString = " ";

        public event PropertyChangedEventHandler PropertyChanged;
       
        private bool isInitialScreenVisible;
        private bool isHttpCallServiceGridVisible;
        private bool isHttpCallCreationResultVisible;
        private bool isActiveCallGridVisible;
        private bool isVideoGridVisible;
        private bool isAboutScreenGridVisible;
        private bool isDesktopSharingBtnVisible;
        private bool isConferenceControlsBtnVisible;
        private bool isCollaborationBtnVisible;        

        private String muteBtnContent;
        private String desktopSharingBtnContent;
        private String callDurationContent;
        private String callStateContent;

        DispatcherTimer timer = new DispatcherTimer();
        Stopwatch stopWatch = new Stopwatch();

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
        public String MuteBtnContent
        {
            get { return muteBtnContent; }
            set
            {
                if (muteBtnContent != value)
                {
                    muteBtnContent = value;
                    OnPropertyChanged("MuteBtnContent");  // To notify when the property is changed
                }
            }
        }
        public String CallStateContent
        {
            get { return callStateContent; }
            set
            {
                if (callStateContent != value)
                {
                    callStateContent = value;
                    OnPropertyChanged("CallStateContent");  // To notify when the property is changed
                }
            }
        }
        public String CallDurationContent
        {
            get { return callDurationContent; }
            set
            {
                if (callDurationContent != value)
                {
                    callDurationContent = value;
                    OnPropertyChanged("CallDurationContent");  // To notify when the property is changed
                }
            }
        }       

        public bool IsInitialScreenVisible
        {
            get { return isInitialScreenVisible; }
            set
            {
                if (isInitialScreenVisible != value)
                {
                    isInitialScreenVisible = value;
                    OnPropertyChanged("IsInitialScreenVisible");  // To notify when the property is changed
                }
            }
        } 

        public bool IsConferenceControlsBtnVisible
        {
            get { return isConferenceControlsBtnVisible; }
            set
            {
                if (isConferenceControlsBtnVisible != value)
                {
                    isConferenceControlsBtnVisible = value;
                    OnPropertyChanged("IsConferenceControlsBtnVisible");  // To notify when the property is changed
                }
            }
        }

        public bool IsAboutScreenGridVisible
        {
            get { return isAboutScreenGridVisible; }
            set
            {
                if (isAboutScreenGridVisible != value)
                {
                    isAboutScreenGridVisible = value;
                    OnPropertyChanged("IsAboutScreenGridVisible");  // To notify when the property is changed
                }
            }
        }

        public bool IsVideoGridVisible
        {
            get { return isVideoGridVisible; }
            set
            {
                if (isVideoGridVisible != value)
                {
                    isVideoGridVisible = value;
                    OnPropertyChanged("IsVideoGridVisible");  // To notify when the property is changed
                }
            }
        }

        public bool IsActiveCallGridVisible
        {
            get { return isActiveCallGridVisible; }
            set
            {
                if (isActiveCallGridVisible != value)
                {
                    isActiveCallGridVisible = value;
                    OnPropertyChanged("IsActiveCallGridVisible");  // To notify when the property is changed
                }
            }
        }        

        public bool IsHttpCallServiceGridVisible
        {
            get { return isHttpCallServiceGridVisible; }
            set
            {
                if (isHttpCallServiceGridVisible != value)
                {
                    isHttpCallServiceGridVisible = value;
                    OnPropertyChanged("IsHttpCallServiceGridVisible");  // To notify when the property is changed
                }
            }
        }

        public bool IsHttpCallCreationResultVisible
        {
            get { return isHttpCallCreationResultVisible; }
            set
            {
                if (isHttpCallCreationResultVisible != value)
                {
                    isHttpCallCreationResultVisible = value;
                    OnPropertyChanged("IsHttpCallCreationResultVisible");  // To notify when the property is changed
                }
            }
        }

        public MainWindow()
        {
            InitializeComponent();
            IsInitialScreenVisible = true;
            CallStateContent = String.Empty;
            CallDurationContent = String.Empty;
            ConferenceUrlBox.Text = SampleConferenceApp.Properties.Settings.Default.ConferenceUrl;

            DataContext = this;

            SDKManager sdkmanager = SDKManager.GetInstance();
            sdkmanager.UserRegistrationSuccessfulEvent += HandleUserRegistration;
            sdkmanager.UserRegistrationInProgressEvent += HandleUserRegistrationInProgress;
            sdkmanager.UserUnRegistrationSuccessfulEvent += HandleUserUnRegistration;
            sdkmanager.ClientShutdownCompletedEvent += HandleClientShutdown;           

            CallManager callmanager = CallManager.GetInstance();
            callmanager.CallStateChangedEvent += HandleCallStateChangedEvent;
            callmanager.CallStartedEvent += HandleCallStartedEvent;
            callmanager.CallEstablishedEvent += HandleCallEstablishedEvent;
            callmanager.MuteEvent += HandleMuteEvent;
            callmanager.UpdateVideoUIEvent += HandleUpdateVideoUIEvent;
            callmanager.RemoteAddressChangedEvent += HandleRemoteAddressChangedEvent;
            callmanager.ParticipantsChangedEvent += HandleParticipantsChangedEvent;
            callmanager.ConferenceStartedEvent += HandleConferenceStartedEvent;
            callmanager.ConferenceCapabilitiesChangedEvent += HandleConferenceCapabilitiesChangedEvent;

            timer.Tick += new EventHandler(HandleTimerTickEvent);
            timer.Interval = new TimeSpan(0, 0, 0, 0, 1);
        }
        #region Event handlers to handle UI       

        public void HandleUserRegistration(object sender, EventArgs e)
        {
            IsInitialScreenVisible = false;
            IsHttpCallServiceGridVisible = true;
        }

        public void HandleUserRegistrationInProgress(object sender, EventArgs e)
        {            
        }

        public void HandleUserUnRegistration(object sender, EventArgs e)
        {        
        }

        public void HandleClientShutdown(object sender, EventArgs e)
        {
            App.Current.Shutdown();
        }     

        public void HandleCallStateChangedEvent(object sender, EventArgs e)
        {
            if (CallManager.CurrentCall != null)
            {
                CallStateContent = CallManager.CurrentCall.State.ToString();
                if (CallManager.CurrentCall.State == CallState.Established)
                {
                    stopWatch.Start();
                    timer.Start();
                    DisplayParticipantList();
                    if (CallManager.CurrentCall.AudioMuted)
                    {
                        MuteBtnContent = "ON";
                    }
                    else
                    {
                        MuteBtnContent = "OFF";
                    }
                }

                if (CallManager.CurrentCall.State == CallState.Ended || CallManager.CurrentCall.State == CallState.Ignored)
                {
                    if (stopWatch.IsRunning)
                    {
                        stopWatch.Stop();
                        stopWatch.Reset();
                    }
                    CallManager.GetInstance().StopLocalVideo();
                    CallManager.GetInstance().StopVideoWindow();
                    IsHttpCallServiceGridVisible = true;
                    IsActiveCallGridVisible = false;
                    IsVideoGridVisible = false;
                }
            }
        }

        public void HandleCallStartedEvent(object sender, EventArgs e)
        {
            IsHttpCallServiceGridVisible = false;
            IsActiveCallGridVisible = true;
        }

        public void HandleCallEstablishedEvent(object sender, EventArgs e)
        {
            IsHttpCallServiceGridVisible = false;
            IsActiveCallGridVisible = true;
        }

        public void HandleMuteEvent(object sender, EventArgs e)
        {
            Call call = SDKManager.GetUser().CallService.ActiveCall;
            if (call != null)
            {
                if (call.AudioMuted)
                {
                    MuteBtnContent = "ON";
                }
                else
                {
                    MuteBtnContent = "OFF";
                }
            }
        }

        public void HandleParticipantsChangedEvent(object sender, EventArgs e)
        {
            DisplayParticipantList();
        }

        public void HandleConferenceStartedEvent(object sender, EventArgs e)
        {
        }

        public void HandleConferenceCapabilitiesChangedEvent(object sender, EventArgs e)
        {
            if (CallManager.ConferenceInstance != null && CallManager.ConferenceInstance.ModerateConferenceCapability.Allowed)
            {
                IsConferenceControlsBtnVisible = true;
            }
            else
            {
                Console.WriteLine("Moderator capability not allowed");
            }
        }

        /// <summary>
        /// Event handler to handle timer tick event
        /// </summary>
        void HandleTimerTickEvent(object sender, EventArgs e)
        {
            if (stopWatch.IsRunning)
            {
                TimeSpan ts = stopWatch.Elapsed;
                CallDurationContent = String.Format("{0:00}:{1:00}:{2:00}", ts.Hours, ts.Minutes, ts.Seconds);
            }
        }
        public void HandleUpdateVideoUIEvent(object sender, EventArgs e)
        {
            IsVideoGridVisible = true;
        }

        public void HandleRemoteAddressChangedEvent(object sender, EventArgs e)
        {
            DisplayParticipantList();
        }

        #endregion

        #region Call service settings , Messaging service settings , Device service settings and about screen 
                      

        private void aboutBtn_Click(object sender, RoutedEventArgs e)
        {
            var mainAssembly = Assembly.GetEntryAssembly();
            var mainInfo = FileVersionInfo.GetVersionInfo(mainAssembly.Location);            
            appVersionLabel.Content = string.Format("Sample App Version: {0}({1})", mainInfo.FileVersion, mainInfo.ProductVersion);
            avayaClientServicesLabel.Content = string.Format("Client SDK Version: {0}", Client.Version);
            appBuildDateLabel.Content = string.Format("Build date: {0}", new FileInfo(Assembly.GetExecutingAssembly().Location).LastWriteTime);
            IsAboutScreenGridVisible = true;           
            IsHttpCallServiceGridVisible = false;
        }

        private void aboutBackBtn_Click(object sender, RoutedEventArgs e)
        {
            IsAboutScreenGridVisible = false;
            IsHttpCallServiceGridVisible = true;
        }

        #endregion Call service settings , Messaging service settings , Device service settings and about screen 

        #region Call Service
        

        private void endCallBtn_Click(object sender, RoutedEventArgs e)
        {
            CallManager callManager = CallManager.GetInstance();
            Call call = CallManager.CurrentCall;
            if (call != null)
            {
                CallManager.GetInstance().StopRinging();
                if (call.IsVideoActive)
                {
                    callManager.StopVideoWindow();
                }
                callManager.EndCall(call);
                if (stopWatch.IsRunning)
                {
                    stopWatch.Stop();
                    stopWatch.Reset();
                }
            }
            IsVideoGridVisible = false;
            IsHttpCallServiceGridVisible = true;
            IsActiveCallGridVisible = false;
        }        

        private async void httpAudioCallBtn_Click(object sender, RoutedEventArgs e)
        {
            if (ConferenceUrlBox.Text != String.Empty)
            {
                SampleConferenceApp.Properties.Settings.Default.ConferenceUrl = ConferenceUrlBox.Text;
                SampleConferenceApp.Properties.Settings.Default.Save();
                IsConferenceControlsBtnVisible = false;
                IsHttpCallCreationResultVisible = false;
                participantList.Items.Clear();
                CallDurationContent = string.Empty;
                MuteBtnContent = "OFF";
                var uri = new UriBuilder(ConferenceUrlBox.Text.Trim()).Uri;
                var parameters = HttpUtility.ParseQueryString(uri.Query);
                var result = await HttpUaCallManager.GetInstance().CreateHttpCall(new AppCallCreationInfo
                {
                    PortalUrl = uri.AbsoluteUri,
                    ConferenceId = parameters["ID"],
                    ShouldLoginAsGuest = AsGuestCheckBox.IsChecked.Value,
                    Username = AsGuestCheckBox.IsChecked.Value ? YourNameBox.Text : UsernameBox.Text,
                    Password = AsGuestCheckBox.IsChecked.Value ? string.Empty : PasswordBox.Text
                });
                if (result != null)
                {
                    IsHttpCallCreationResultVisible = true;
                    HttpCallCreationResult.Content = "Failed to join: " + result.Error;
                    return;
                }
                CallManager.GetInstance().StartCall(CallManager.OutgoingCall);
                IsHttpCallServiceGridVisible = false;
                IsActiveCallGridVisible = true;
            }
            else
            {
                NotificationHelper.ShowNotification("Enter number to call");
            }
        }        

        private async void httpVideoCallBtn_Click(object sender, RoutedEventArgs e)
        {
            if (ConferenceUrlBox.Text != String.Empty)
            {
                SampleConferenceApp.Properties.Settings.Default.ConferenceUrl = ConferenceUrlBox.Text;
                SampleConferenceApp.Properties.Settings.Default.Save();
                CallManager callManager = CallManager.GetInstance();
                IsConferenceControlsBtnVisible = false;
                IsHttpCallCreationResultVisible = false;
                participantList.Items.Clear();
                CallDurationContent = string.Empty;
                MuteBtnContent = "OFF";
                var uri = new UriBuilder(ConferenceUrlBox.Text.Trim()).Uri;
                var parameters = HttpUtility.ParseQueryString(uri.Query);
                var result = await HttpUaCallManager.GetInstance().CreateHttpCall(new AppCallCreationInfo
                {
                    PortalUrl = uri.AbsoluteUri,
                    ConferenceId = parameters["ID"],
                    ShouldLoginAsGuest = AsGuestCheckBox.IsChecked.Value,
                    Username = AsGuestCheckBox.IsChecked.Value ? YourNameBox.Text : UsernameBox.Text,
                    Password = AsGuestCheckBox.IsChecked.Value ? string.Empty : PasswordBox.Text
                });
                if (result != null)
                {
                    IsHttpCallCreationResultVisible = true;
                    HttpCallCreationResult.Content = "Failed to join: " + result.Error;
                    return;
                }
                callManager.AddVideo(CallManager.OutgoingCall);
                CallManager.GetInstance().StartCall(CallManager.OutgoingCall);
                IsHttpCallServiceGridVisible = false;
                IsActiveCallGridVisible = true;
            }
            else
            {
                NotificationHelper.ShowNotification("Enter number to call");
            }
        }

        private void muteBtn_Click(object sender, RoutedEventArgs e)
        {
            CallManager callManager = CallManager.GetInstance();
            callManager.MuteCall();
        }

        private void conferenceControlsBtn_Click(object sender, RoutedEventArgs e)
        {
            ConferenceControlsWindow conferenceControlsWindow = new ConferenceControlsWindow();
            conferenceControlsWindow.Owner = this;
            conferenceControlsWindow.Show();
        }

        /// <summary>
        /// Display active call participant list on UI
        /// </summary>
        public void DisplayParticipantList()
        {
            participantList.Items.Clear();
            Call call = SDKManager.GetUser().CallService.ActiveCall;
            if (call != null && call.IsConference)
            {
                call.Conference.Participants.ForEach(p => participantList.Items.Add(p));
            }
        }
        #endregion Call Service

        /// <summary>
        /// Event occurs when window is closing
        /// </summary>    
        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            SDKManager csdkManager = SDKManager.GetInstance();
            if (SDKManager.UserInstance != null)
            {
                csdkManager.RemoveUser(SDKManager.UserInstance);
            }
            csdkManager.UserRegistrationSuccessfulEvent -= HandleUserRegistration;
            csdkManager.UserRegistrationInProgressEvent -= HandleUserRegistrationInProgress;
            csdkManager.UserUnRegistrationSuccessfulEvent -= HandleUserUnRegistration;

            CallManager callManager = CallManager.GetInstance();
            callManager.CallStateChangedEvent -= HandleCallStateChangedEvent;
            callManager.CallStartedEvent -= HandleCallStartedEvent;
            callManager.CallEstablishedEvent -= HandleCallEstablishedEvent;
            callManager.MuteEvent -= HandleMuteEvent;
            callManager.UpdateVideoUIEvent -= HandleUpdateVideoUIEvent;
            callManager.RemoteAddressChangedEvent -= HandleRemoteAddressChangedEvent;
            callManager.ParticipantsChangedEvent -= HandleParticipantsChangedEvent;
            callManager.ConferenceStartedEvent -= HandleConferenceStartedEvent;
            callManager.ConferenceCapabilitiesChangedEvent -= HandleConferenceCapabilitiesChangedEvent;
            CompositionTarget.Rendering -= (LocalVideo.Source as VideoRenderer2).onRendering;
            CompositionTarget.Rendering -= (RemoteVideo.Source as VideoRenderer2).onRendering;
            timer.Tick -= HandleTimerTickEvent;

            if (SDKManager.ClientInstance != null)
            {
                e.Cancel = true;  // wait for client shutdown
                csdkManager.ShutdownClient();
            }
        }

        /// <summary>
        /// Auto login function - Get stored configuration values
        /// </summary>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {            
            CallManager.GetInstance().localVideo.Clear();
            CallManager.GetInstance().remoteVideo.Clear();
            CompositionTarget.Rendering += (LocalVideo.Source as VideoRenderer2).onRendering;
            CompositionTarget.Rendering += (RemoteVideo.Source as VideoRenderer2).onRendering;
            CallManager.GetInstance().AddLocalVideoRenderer(LocalVideo.Source as VideoRenderer2);
            CallManager.GetInstance().AddRemoteVideoRenderer(RemoteVideo.Source as VideoRenderer2);
        }
    }
}
