/// <summary>
        /// Refresh the methods tree.
        /// </summary>
        /// <returns>False if could not connect to the current API installation.</returns>
        private bool RefreshTree()
        {
            /* Retrieving a list of all API methods. */

            List <ApiMethod> methods = null;

            try
            {
                methods = this.apiConnector.GetMethods();
            }
            catch (WebException ex)
            {
                MessageBox.Show("Could not connect to selected installation.\n" + ex.Message + "\n"
                                + ApiConnector.ReadResponse(ex.Response), "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
                return(false);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Could not connect to selected installation.\n" + ex.Message, "Error",
                                MessageBoxButton.OK, MessageBoxImage.Warning);
                return(false);
            }

            /* Building a tree of modules and methods. This is done by analyzing method names. */

            foreach (ApiMethod method in methods)
            {
                string[]     path        = method.name.Split('/');
                TreeViewItem currentnode = null;
                for (var i = 1; i < path.Length; i++)
                {
                    string         part            = path[i];
                    bool           already_present = false;
                    ItemCollection items           = (i == 1) ? this.methodsTreeView.Items : currentnode.Items;
                    foreach (TreeViewItem item in items)
                    {
                        if ((string)item.Header == part)
                        {
                            already_present = true;
                            currentnode     = item;
                        }
                    }
                    if (!already_present)
                    {
                        currentnode = new TreeViewItem {
                            Header = part
                        };
                        if (i == path.Length - 1)
                        {
                            currentnode.Tag     = method;
                            currentnode.ToolTip = method.brief_description;
                        }
                        items.Add(currentnode);
                    }
                }
            }

            /* Expand all nodes of the tree (if the are more than 50 methods in this installation,
             * then we skip this step), and select an initial method (request_token). */

            foreach (TreeViewItem item in this.methodsTreeView.Items)
            {
                if (methods.Count < 50)
                {
                    item.ExpandSubtree();
                }
                if ((string)item.Header == "oauth")
                {
                    item.ExpandSubtree();
                    foreach (TreeViewItem subitem in item.Items)
                    {
                        if ((string)subitem.Header == "request_token")
                        {
                            subitem.IsSelected = true;
                        }
                    }
                }
            }
            return(true);
        }
        /// <summary>
        /// User clicks the "Quick Fill" button.
        /// </summary>
        private void quickFillButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.consumerKeyTextbox.Text == "")
            {
                if (MessageBox.Show("In order to get Access Tokens, you have to register a Consumer Key first. " +
                                    "Would you like to register a new Consumer Key now?", "Consumer Key is missing", MessageBoxButton.OKCancel,
                                    MessageBoxImage.Question) == MessageBoxResult.OK)
                {
                    /* Direct the user to USOS API Developer Center. */
                    try
                    {
                        System.Diagnostics.Process.Start(this.apiConnector.GetURL(new ApiMethod {
                            name = "developers/"
                        }));
                    }
                    catch (Exception)
                    {
                        MessageBox.Show("It appears your system doesn't know in which application to open a http:// protocol. Check your browser settings.\n\n" + this.apiConnector.GetURL(new ApiMethod {
                            name = "developers/"
                        }));
                        return;
                    }
                }
                return;
            }

            /* Show initial dialog, user will choose desired scopes. */

            var initialDialog = new QuickFillWindow();

            initialDialog.Owner = this;
            if (initialDialog.ShowDialog() == false)
            {
                return; // user cancelled
            }
            /* Retrieve a list of selected scopes. */

            List <string> scopeKeys = initialDialog.GetSelectedScopeKeys();

            /* Build request_token URL. We will use 'oob' as callback, and
             * require scopes which the user have selected. */

            var request_token_args = new Dictionary <string, string>();

            request_token_args.Add("oauth_callback", "oob");
            if (scopeKeys.Count > 0)
            {
                request_token_args.Add("scopes", string.Join("|", scopeKeys));
            }

            try
            {
                /* Get and parse the request_token response string. */

                string tokenstring;
                try
                {
                    string request_token_url = this.apiConnector.GetURL(new ApiMethod {
                        name = "services/oauth/request_token"
                    },
                                                                        request_token_args, this.consumerKeyTextbox.Text, this.consumerSecretTextbox.Text, "", "", true);
                    tokenstring = this.apiConnector.GetResponse(request_token_url);
                }
                catch (WebException ex)
                {
                    /* Let's try the same URL, but without SSL. This will allow it to work on
                     * developer installations (which do not support SSL by default). If it still
                     * throws exceptions, pass. */

                    string request_token_url = this.apiConnector.GetURL(new ApiMethod {
                        name = "services/oauth/request_token"
                    },
                                                                        request_token_args, this.consumerKeyTextbox.Text, this.consumerSecretTextbox.Text, "", "", false);
                    tokenstring = this.apiConnector.GetResponse(request_token_url);
                }

                string   request_token        = null;
                string   request_token_secret = null;
                string[] parts = tokenstring.Split('&');
                foreach (string part in parts)
                {
                    if (part.StartsWith("oauth_token="))
                    {
                        request_token = part.Substring("oauth_token=".Length);
                    }
                    if (part.StartsWith("oauth_token_secret="))
                    {
                        request_token_secret = part.Substring("oauth_token_secret=".Length);
                    }
                }
                if (request_token == null || request_token_secret == null)
                {
                    MessageBox.Show("Couldn't parse request token. Try to do this sequence manually!", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                /* Build authorize URL and open it in user's browser. */

                var authorize_args = new Dictionary <string, string>();
                authorize_args.Add("oauth_token", request_token);
                var authorize_url = this.apiConnector.GetURL(new ApiMethod {
                    name = "services/oauth/authorize"
                }, authorize_args);
                try
                {
                    System.Diagnostics.Process.Start(authorize_url);
                }
                catch (Exception)
                {
                    MessageBox.Show("It appears your system doesn't know in which application to open a http:// protocol. Check your browser settings.\n\n" + authorize_url);
                    return;
                }

                /* Open a with PIN request and wait for user's entry. */

                var pinWindow = new QuickFillPINWindow();
                pinWindow.Owner = this;
                pinWindow.ShowDialog();
                string verifier = pinWindow.GetPIN();

                /* Build the access_token URL. */

                var access_token_args = new Dictionary <string, string>();
                access_token_args.Add("oauth_verifier", verifier);
                try
                {
                    var access_token_url = this.apiConnector.GetURL(new ApiMethod {
                        name = "services/oauth/access_token"
                    }, access_token_args,
                                                                    this.consumerKeyTextbox.Text, this.consumerSecretTextbox.Text, request_token, request_token_secret, true);
                    tokenstring = this.apiConnector.GetResponse(access_token_url);
                }
                catch (WebException ex)
                {
                    /* Let's try the same URL, but without SSL. This will allow it to work on
                     * developer installations (which do not support SSL by default). If it still
                     * throws exceptions, pass. */

                    var access_token_url = this.apiConnector.GetURL(new ApiMethod {
                        name = "services/oauth/access_token"
                    }, access_token_args,
                                                                    this.consumerKeyTextbox.Text, this.consumerSecretTextbox.Text, request_token, request_token_secret, false);
                    tokenstring = this.apiConnector.GetResponse(access_token_url);
                }


                /* Get and parse the access_token response string. */

                string access_token        = null;
                string access_token_secret = null;
                parts = tokenstring.Split('&');
                foreach (string part in parts)
                {
                    if (part.StartsWith("oauth_token="))
                    {
                        access_token = part.Substring("oauth_token=".Length);
                    }
                    if (part.StartsWith("oauth_token_secret="))
                    {
                        access_token_secret = part.Substring("oauth_token_secret=".Length);
                    }
                }
                if (access_token == null || access_token_secret == null)
                {
                    MessageBox.Show("Couldn't parse access token. Try to do this sequence manually!", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                /* Fill up the token textboxes with an Access Token we received. */

                this.tokenTextbox.Text       = access_token;
                this.tokenSecretTextbox.Text = access_token_secret;
            }
            catch (WebException ex)
            {
                MessageBox.Show("A problem occured. Couldn't complete the Quick Fill.\n\n" + ex.Message + "\n"
                                + ApiConnector.ReadResponse(ex.Response), "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
            }
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)
            {
                System.Deployment.Application.ApplicationDeployment ad = System.Deployment.Application.ApplicationDeployment.CurrentDeployment;
                this.Title += " (v. " + ad.CurrentVersion.ToString() + ")";
            }

            this.varsCache.BindWithTextBox("consumer_key", this.consumerKeyTextbox);
            this.varsCache.BindWithTextBox("consumer_secret", this.consumerSecretTextbox);
            this.varsCache.BindWithTextBox("token", this.tokenTextbox);
            this.varsCache.BindWithTextBox("token_secret", this.tokenSecretTextbox);

            /* We use a "mother installation" for the first USOS API request. We need to
             * get a list of all USOS API installations. */

            var motherInstallation = new ApiInstallation
            {
                base_url = "http://apps.usos.edu.pl/" // will change when out of Beta!
            };
            this.apiConnector = new ApiConnector(motherInstallation);
            this.apiConnector.BeginRequest += new EventHandler(apiConnector_BeginRequest);
            this.apiConnector.EndRequest += new EventHandler(apiConnector_EndRequest);

            /* Fill up the installations list. */

            try
            {
                this.installationsComboBox.Items.Clear();
                var installations = this.apiConnector.GetInstallations();
                installations.Add(new ApiInstallation() { base_url = "http://127.0.0.1:8000/" });
                foreach (var installation in installations)
                {
                    this.installationsComboBox.Items.Add(new ComboBoxItem
                    {
                        Content = installation.base_url,
                        Tag = installation
                    });
                }
            }
            catch (WebException)
            {
                MessageBox.Show("Error occured when trying to access USOS API mother server. Could not populate USOS API installations list.",
                    "Network error", MessageBoxButton.OK, MessageBoxImage.Exclamation);
            }

            if (this.installationsComboBox.Items.Count > 0)
            {
                /* Now we have a list of all installations in a combo box. We choose
                 * one of them. */

                this.installationsComboBox.SelectedIndex = 0;
                this.ReloadInstallation();
            }
        }