/// <summary>
        /// </summary>
        /// <param name="fastPackageReference"></param>
        /// <param name="request">
        ///     An object passed in from the CORE that contains functions that can be used to interact with the
        ///     CORE and HOST
        /// </param>
        public void InstallPackage(string fastPackageReference, NuGetRequest request)
        {
            // Nice-to-have put a debug message in that tells what's going on.
            request.Debug("Calling '{0}::InstallPackage' '{1}'", PackageProviderName, fastPackageReference);

            var pkgRef = request.GetPackageByFastpath(fastPackageReference);
            if (pkgRef == null) {
                request.Error(ErrorCategory.InvalidArgument, fastPackageReference, Constants.Messages.UnableToResolvePackage);
                return;
            }

            // need to make sure that the original package's sources list is tried first.
            request.OriginalSources = pkgRef.Sources;

            var dependencies = request.GetUninstalledPackageDependencies(pkgRef).Reverse().ToArray();
            int progressId = 0;

            if (dependencies.Length > 0) {
                progressId = request.StartProgress(0, "Installing package '{0}'", pkgRef.GetCanonicalId(request));
            }
            var n = 0;
            foreach (var d in dependencies) {
                request.Progress(progressId, (n*100/(dependencies.Length + 1)) + 1, "Installing dependent package '{0}'", d.GetCanonicalId(request));
                if (!request.InstallSinglePackage(d)) {
                    request.Error(ErrorCategory.InvalidResult, pkgRef.GetCanonicalId(request), Constants.Messages.DependentPackageFailedInstall, d.GetCanonicalId(request));
                    return;
                }
                n++;
                request.Progress(progressId, (n*100/(dependencies.Length + 1)), "Installed dependent package '{0}'", d.GetCanonicalId(request));
            }

            // got this far, let's install the package we came here for.
            if (!request.InstallSinglePackage(pkgRef)) {
                // package itself didn't install.
                // roll that back out everything we did install.
                // and get out of here.
                request.Error(ErrorCategory.InvalidResult, pkgRef.GetCanonicalId(request), Constants.Messages.PackageFailedInstall, pkgRef.GetCanonicalId(request));
                request.CompleteProgress(progressId, false);
            }
            request.CompleteProgress(progressId, true);
        }
        /// <summary>
        /// Install a single package. Also install any of its dependency if they are available (the dependency will be installed first).
        /// For dependencies, we will only get those that are not installed.
        /// Operation is either install or download
        /// installOrDownloadFunction is a function that takes in a packageitem and performs either install or download on it
        /// </summary>
        /// <param name="pkgItem"></param>
        /// <param name="request"></param>
        /// <param name="operation"></param>
        /// <param name="installOrDownloadFunction"></param>
        /// <returns></returns>
        internal static bool InstallOrDownloadPackageHelper(PackageItem pkgItem, NuGetRequest request, string operation, Func<PackageItem, bool> installOrDownloadFunction)
        {
            // pkgItem.Sources is the source that the user input. The request will try this source.
            request.OriginalSources = pkgItem.Sources;

            int progressId = 0;

            bool hasDependencyLoop = false;
            // Get the dependencies that are not already installed
            var dependencies = NuGetClient.GetPackageDependenciesToInstall(request, pkgItem, ref hasDependencyLoop).ToArray();
             
            // If there is a dependency loop. Warn the user and don't install the package
            if (hasDependencyLoop)
            {
                // package itself didn't install. Report error
                request.WriteError(ErrorCategory.DeadlockDetected, pkgItem.Id, Constants.Messages.DependencyLoopDetected, pkgItem.Id);
                return false;
            }

            // request may get canceled if there is a package dependencies missing
            if (request.IsCanceled)
            {
                return false;
            }

            int n = 0;
            int numberOfDependencies = dependencies.Count();

            // Start progress
            progressId = request.StartProgress(0, string.Format(CultureInfo.InvariantCulture, Messages.InstallingOrDownloadingPackage, operation, pkgItem.Id));

            try
            {
                // check that this package has dependency and the user didn't want to skip dependencies
                if (numberOfDependencies > 0)
                {
                    // let's install dependencies
                    foreach (var dep in dependencies)
                    {
                        request.Progress(progressId, (n * 100 / (numberOfDependencies + 1)) + 1, string.Format(CultureInfo.InvariantCulture, Messages.InstallingOrDownloadingDependencyPackage, operation, dep.Id));
                        // Check that we successfully installed the dependency
                        if (!installOrDownloadFunction(dep))
                        {
                            request.WriteError(ErrorCategory.InvalidResult, dep.Id, Constants.Messages.DependentPackageFailedInstallOrDownload, dep.Id, CultureInfo.CurrentCulture.TextInfo.ToLower(operation));
                            return false;
                        }
                        n++;
                        request.Progress(progressId, (n * 100 / (numberOfDependencies + 1)), string.Format(CultureInfo.InvariantCulture, Messages.InstalledOrDownloadedDependencyPackage, operation, dep.Id));
                    }
                }

                // Now let's install the main package
                if (installOrDownloadFunction(pkgItem))
                {
                    return true;
                }
            }
            catch (Exception ex)
            {
                ex.Dump(request);
            }
            finally
            {
                // Report that we have completed installing the package and its dependency this does not mean there are no errors.
                // Just that it's completed.
                request.CompleteProgress(progressId, false);
            }
            
            // package itself didn't install. Report error
            request.WriteError(ErrorCategory.InvalidResult, pkgItem.Id, Constants.Messages.PackageFailedInstallOrDownload, pkgItem.Id, CultureInfo.CurrentCulture.TextInfo.ToLower(operation));

            return false;
        }