/// <summary>Handles the ok button being touched when an exception is displayed.</summary>
 /// <param name="sender">The parameter is not used.</param>
 /// <param name="e">The parameter is not used.</param>
 private void ExceptionOkClicked(object sender, RoutedEventArgs e)
 {
     this.ExceptionPanel.Visibility = Visibility.Collapsed;
     this.OnStateChange(ConnectionState.Disconnected);
     this.connection = null;
 }
        /// <summary>Start the process of connecting to the server.</summary>
        /// <param name="server">The server address</param>
        /// <param name="port">The TCP port number to connect on</param>
        /// <param name="password">The password to use for the connection.</param>
        private void Connect(string server, int port, string password)
        {
            this.client = new TcpClient();

            this.SetStatusText("Connecting to " + server);

            Task.Run(async () =>
                {
                    try
                    {
                        using (var cancellation = new CancellationTokenSource())
                        {
                            cancellation.CancelAfter(TimeSpan.FromSeconds(30));
                            await Task.Run(() => this.client.ConnectAsync(server, port), cancellation.Token);
                        }

                        var stream = this.client.GetStream();

                        this.connectionPort = Connection.CreateFromStream(stream, this.HandleRectangle, this.HandleConnectionState, this.HandleException);
                    }
                    catch (Exception e)
                    {
                        if (e.InnerException != null)
                        {
                            this.SetStatusText("Error connecting: " + e.InnerException.Message);
                        }
                        else
                        {
                            this.SetStatusText("Error connecting: " + e.Message);
                        }
                    }

                    await DoConnect(password);
                });
        }
        /// <summary>Handles the connect button being tapped.</summary>
        /// <param name="sender">The parameter is not used.</param>
        /// <param name="e">The parameter is not used.</param>
        /// <remarks>This manages the connect, handshake, initialize flow of the VNC protocol.</remarks>
        private void ClickConnect(object sender, RoutedEventArgs e)
        {
            var server = this.Server.Text;
            var port = this.Port.Text;
            var password = this.Password.Password;
            var isSecure = (bool)this.IsSecure.IsChecked;

            var client = new StreamSocket();

            Task.Run(async () =>
            {
                try
                {
                    var host = new HostName(server);

                    await client.ConnectAsync(host, port, isSecure ? SocketProtectionLevel.Ssl : SocketProtectionLevel.PlainSocket);

                    this.connection = Connection.CreateFromStreamSocket(
                        client,
                        r => this.EnqueueUpdate(() => this.OnRectangle(r)),
                        s => this.EnqueueUpdate(() => OnStateChange(s)),
                        f => this.EnqueueUpdate(() => OnException(f)));

                    var requiresPassword = await this.connection.HandshakeAsync();

                    if (requiresPassword)
                    {
                        if (string.IsNullOrEmpty(password))
                        {
                            password = await this.GetPassword();
                        }

                        await this.connection.SendPasswordAsync(password);
                    }

                    var name = await this.connection.InitializeAsync(shareDesktop: true);

                    var connectionInfo = this.connection.GetConnectionInfo();

                    this.Invoke(() =>
                    {
                        Settings.SetLocalSettingAsync("Server", server);
                        Settings.SetLocalSettingAsync("Port", port);
                        Settings.SetLocalSettingAsync("Password", password, isEncrypted: true);
                        Settings.SetLocalSettingAsync("IsSecure", isSecure ? "True" : "False");

                        this.StartFrameBuffer(connectionInfo);
                    });
                }
                catch (Exception exception)
                {
                    this.Invoke(() =>
                    {
                        this.OnException(exception);
                    });
                }
            });
        }
        /// <summary>Disconnect from the server if possible</summary>
        private void Disconnect()
        {
            Task.Run(
                () =>
                {
                    if (this.connectionPort != null)
                    {
                        this.connectionPort.ShutdownAsync().Wait();
                        this.connectionPort = null;
                    }
                });
            
            if (this.client != null &&
                this.client.Connected)
            {
                this.client.Client.Disconnect(true);
                this.client.Close();
            }

            this.IsConnected = false;
        }