/// <summary>
        /// Attempts to fulfill the requirements to complete an orbital logistics transfer.
        /// </summary>
        /// <param name="vessel"></param>
        /// <param name="resourceUnits">The amount of the transport resource required for the transfer.</param>
        /// <returns><c>true</c> if the requirements were met, <c>false</c> otherwise.</returns>
        public static bool DeductTransportCost(this Vessel vessel, double resourceUnits)
        {
            if (!vessel.CanAffordTransport(resourceUnits))
            {
                return(false);
            }

            // Deduct resource units from vessel
            PartResourceDefinition transportCredits = PartResourceLibrary.Instance.GetDefinition("TransportCredits");

            vessel.ExchangeResources(transportCredits.id, -resourceUnits);

            return(true);
        }
        /// <summary>
        /// Called by <see cref="MonoBehaviour"/>.OnGUI to render the UI.
        /// </summary>
        /// <param name="windowId"></param>
        protected override void DrawWindowContents(int windowId)
        {
            // Origin vessel section header
            GUILayout.BeginHorizontal();
            GUILayout.Label("Origin", UIHelper.labelStyle, GUILayout.Width(80));
            GUILayout.Label(_module.vessel.vesselName, UIHelper.whiteLabelStyle);
            GUILayout.EndHorizontal();  // origin vessel section

            // Destination vessel selection section
            GUILayout.BeginHorizontal();
            GUILayout.Label("Destination", UIHelper.labelStyle, GUILayout.Width(80));

            // Display Previous button for destination vessel selection
            if (GUILayout.Button(UIHelper.leftArrowSymbol, UIHelper.buttonStyle, GUILayout.Width(30), GUILayout.Height(20)))
            {
                UpdateDestinationVessel(GetPreviousVesselIndex(_destinationVesselIndex));
                _destinationVesselComboBox.SelectedItemIndex = _destinationVesselIndex;
            }

            // Display combo box for destination vessel selection
            _destinationVesselComboBox.Show();

            // Display Next button destination vessel selection
            if (GUILayout.Button(UIHelper.rightArrowSymbol, UIHelper.buttonStyle, GUILayout.Width(30), GUILayout.Height(20)))
            {
                UpdateDestinationVessel(GetNextVesselIndex(_destinationVesselIndex));
                _destinationVesselComboBox.SelectedItemIndex = _destinationVesselIndex;
            }
            GUILayout.EndHorizontal();  // destination selection section

            // Create some visual separation between sections
            GUILayout.Label(string.Empty);

            // Only allow transfers between different vessels
            if (_originVesselIndex != _destinationVesselIndex)
            {
                // Display transferable resources
                _availableResourceScrollViewPosition = GUILayout.BeginScrollView(_availableResourceScrollViewPosition, GUILayout.MinHeight(130));

                // Calculate and display available amount for transferrable resources
                if (_originVessel != null && _destinationVessel != null)
                {
                    string content;
                    double available;

                    // Table header
                    GUILayout.BeginHorizontal();
                    GUILayout.Label(string.Empty, UIHelper.labelStyle, GUILayout.Width(22));
                    GUILayout.Label(" Resource", UIHelper.whiteLabelStyle, GUILayout.Width(165));
                    GUILayout.Label("Available", UIHelper.whiteLabelStyle, GUILayout.MinWidth(150));
                    GUILayout.EndHorizontal();

                    // Table rows
                    foreach (var resource in _originVesselResources)
                    {
                        // Only display resources the origin and destination vessels have in common
                        if (_transferrableResources.Contains(resource.ResourceDefinition))
                        {
                            // String-ify the amount available for transfer
                            available = resource.GetAvailableAmount();

                            content  = available.ToString("F0");
                            content += " / ";
                            content += resource.GetCapacity().ToString("F0");

                            // Display the table row
                            GUILayout.BeginHorizontal();
                            if (GUILayout.Button(UIHelper.downArrowSymbol, UIHelper.buttonStyle, GUILayout.Width(22), GUILayout.Height(22)))
                            {
                                _selectedResource = resource.ResourceDefinition;
                            }
                            GUILayout.Label(" " + resource.Name, UIHelper.yellowLabelStyle, GUILayout.Width(165));
                            GUILayout.Label(content, UIHelper.yellowLabelStyle, GUILayout.MinWidth(150));
                            GUILayout.EndHorizontal();
                        }
                    }
                }
                GUILayout.EndScrollView();  // transferable resources list

                if (_selectedResource != null)
                {
                    // Calculate origin/destination resource amounts
                    var originResource = _originVesselResources
                                         .Where(r => r.ResourceDefinition == _selectedResource)
                                         .Single();

                    var destinationResource = _destinationVesselResources
                                              .Where(r => r.ResourceDefinition == _selectedResource)
                                              .Single();

                    double sourceAvailabe       = originResource.GetAvailableAmount();
                    double destinationAvailable = destinationResource.GetAvailableAmount();
                    double destinationCapacity  = destinationResource.GetCapacity();

                    // Show section for selected resource details and to input transfer amount
                    GUILayout.BeginHorizontal();

                    // Show section for resource details
                    GUILayout.BeginVertical();

                    // Show selected resource
                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Resource:", UIHelper.whiteLabelStyle, GUILayout.Width(80));
                    GUILayout.Label(_selectedResource.name, UIHelper.yellowLabelStyle, GUILayout.Width(120));
                    GUILayout.EndHorizontal();

                    // Show origin amount
                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Origin:", UIHelper.whiteLabelStyle, GUILayout.Width(80));
                    GUILayout.Label(sourceAvailabe.ToString("F1"), UIHelper.yellowLabelStyle, GUILayout.Width(120));
                    GUILayout.EndHorizontal();

                    // Show destination amount and capacity
                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Destination:", UIHelper.whiteLabelStyle, GUILayout.Width(80));
                    GUILayout.Label(
                        string.Format("{0:F1} / {1:F0}", destinationAvailable, destinationCapacity),
                        UIHelper.yellowLabelStyle,
                        GUILayout.Width(120)
                        );
                    GUILayout.EndHorizontal();

                    GUILayout.EndVertical();  // resource details section

                    // Show section for transfer amount
                    GUILayout.BeginVertical();

                    // Show transfer amount header
                    GUILayout.Label("Transfer Amount", UIHelper.centerAlignLabelStyle, GUILayout.Width(165));

                    // Show fill button and text input box
                    GUILayout.BeginHorizontal();
                    if (GUILayout.Button("Fill", UIHelper.buttonStyle, GUILayout.Width(65), GUILayout.Height(25)))
                    {
                        // Determine the amount needed fill the destination vessel with the selected resource
                        double difference = destinationCapacity - destinationAvailable;
                        if (difference > 0)
                        {
                            if (difference > sourceAvailabe)
                            {
                                difference = sourceAvailabe;
                            }

                            _transferAmountText = difference.ToString("F2");
                        }
                    }
                    _transferAmountText = GUILayout.TextField(
                        _transferAmountText, 10, UIHelper.textFieldStyle,
                        GUILayout.Width(95), GUILayout.Height(25)
                        );
                    GUILayout.EndHorizontal();

                    if (GUILayout.Button("Add to Transfer", UIHelper.buttonStyle, GUILayout.Width(165)))
                    {
                        // Parse the transfer amount
                        double amount = 0;
                        if (double.TryParse(_transferAmountText, out amount))
                        {
                            if (amount > 0)
                            {
                                _transfer.AddResource(originResource, amount);
                                _transferAmountText = string.Empty;

                                // Check if adding this transfer amount exceeds the current payload capacity
                                _errorMessageText = !_originVessel.CanAffordTransport(_transfer.CalculateFuelUnits())
                                    ? INSUFFICIENT_FUNDS_MESSAGE
                                    : string.Empty;
                            }
                        }
                    }

                    GUILayout.EndVertical();   // transfer amount section

                    GUILayout.EndHorizontal(); // resource details and transfer amount section
                }

                // Create some visual separation between sections
                GUILayout.Label(string.Empty);

                // Display transfer stats
                if (_transfer != null && _transfer.ResourceRequests.Count > 0)
                {
                    double totalMass = _transfer.TotalMass();
                    float  totalCost = _transfer.CalculateFuelUnits();

                    _transferResourceScrollViewPosition = GUILayout.BeginScrollView(_transferResourceScrollViewPosition, GUILayout.MinHeight(130));

                    // Transfer list header
                    GUILayout.BeginHorizontal();
                    GUILayout.Label(string.Empty, UIHelper.labelStyle, GUILayout.Width(22));
                    GUILayout.Label(" Resource", UIHelper.whiteLabelStyle, GUILayout.MinWidth(155));
                    GUILayout.Label("Quantity", UIHelper.whiteLabelStyle, GUILayout.Width(80));
                    GUILayout.Label("Cost", UIHelper.whiteLabelStyle, GUILayout.Width(80));
                    GUILayout.EndHorizontal();

                    // Transfer list items
                    foreach (var item in _transfer.ResourceRequests.ToArray())
                    {
                        GUILayout.BeginHorizontal();
                        if (GUILayout.Button(UIHelper.deleteSymbol, UIHelper.buttonStyle, GUILayout.Width(22), GUILayout.Height(22)))
                        {
                            _transfer.ResourceRequests.Remove(item);

                            // Check if removing this resource put the transfer back within payload capacity limits
                            if (_originVessel.CanAffordTransport(_transfer.CalculateFuelUnits()))
                            {
                                _errorMessageText = string.Empty;
                            }
                        }
                        GUILayout.Label(" " + item.ResourceDefinition.name, UIHelper.yellowLabelStyle, GUILayout.MinWidth(155));
                        GUILayout.Label(item.TransferAmount.ToString("F2"), UIHelper.yellowLabelStyle, GUILayout.Width(80));
                        GUILayout.Label((totalCost * item.Mass() / totalMass).ToString("F2"), UIHelper.yellowLabelStyle, GUILayout.Width(80));
                        GUILayout.EndHorizontal();
                    }
                    GUILayout.EndScrollView();

                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Total Mass:", UIHelper.whiteLabelStyle, GUILayout.Width(90));
                    GUILayout.Label(totalMass.ToString("F2"), UIHelper.yellowLabelStyle, GUILayout.Width(150));
                    GUILayout.EndHorizontal();

                    GUILayout.BeginHorizontal();
                    var costLabelStyle = _originVessel.CanAffordTransport(totalCost)
                        ? UIHelper.yellowLabelStyle
                        : UIHelper.redLabelStyle;
                    GUILayout.Label("Total Cost:", UIHelper.whiteLabelStyle, GUILayout.Width(90));
                    GUILayout.Label(
                        string.Format("{0:F2} / {1:F0}", totalCost, _originVessel.GetTransportCapacity()),
                        costLabelStyle, GUILayout.Width(150)
                        );
                    GUILayout.EndHorizontal();

                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Transit Time:", UIHelper.whiteLabelStyle, GUILayout.Width(90));
                    GUILayout.Label(
                        Utilities.SecondsToKerbinTime(_transfer.Duration),
                        UIHelper.yellowLabelStyle, GUILayout.Width(150)
                        );
                    GUILayout.EndHorizontal();
                    GUILayout.Label(_errorMessageText, UIHelper.redLabelStyle);
                }
            }
            // Origin and destination vessel are the same, so...
            else
            {
                // Display a message if there is only one vessel in the current SoI that is eligible for OrbLog
                if (_orbLogVesselsInSoI < 2)
                {
                    GUILayout.Label(TOO_FEW_VESSELS_MESSAGE, UIHelper.yellowLabelStyle);
                }
            }

            // Display Start and Cancel buttons
            GUILayout.BeginHorizontal();
            GUILayout.Label(string.Empty, UIHelper.labelStyle, GUILayout.Width(80));
            if (_transfer == null || _transfer.ResourceRequests.Count < 1 || !_originVessel.CanAffordTransport(_transfer.CalculateFuelUnits()))
            {
                // Transfer isn't possible right now, so add a blank label in order to "center" the Cancel button
                GUILayout.Label(string.Empty, GUILayout.Width(60));
            }
            else
            {
                if (GUILayout.Button("Start Transfer", UIHelper.buttonStyle, GUILayout.Width(110)))
                {
                    if (GameSettings.VERBOSE_DEBUG_LOG)
                    {
                        Debug.Log("[MKS] OrbitalLogisiticsTransferCreateView.DrawWindowContents: Start Transfer button pressed.");
                    }

                    _errorMessageText = string.Empty;

                    if (_transfer.Launch(_scenario.PendingTransfers, out _errorMessageText))
                    {
                        ResetAndClose();
                    }
                }
            }
            if (GUILayout.Button("Cancel", UIHelper.buttonStyle, GUILayout.Width(100)))
            {
                ResetAndClose();
            }
            GUILayout.EndHorizontal();

            // Display the contents of the combo boxes
            _destinationVesselComboBox.ShowRest();
        }