private Tuple <String, String> calculateDownloadEstimates(DownloadResource resource, int referencePeriodInSeconds)
            {
                long referencePeriod      = 1000 * referencePeriodInSeconds;
                long currentTimestamp     = DemoUtils.CurrentTimeMillis();
                long downloadPeriod       = currentTimestamp - referencePeriod < _activity.downloadStartTime ? currentTimestamp - _activity.downloadStartTime : referencePeriod;
                long totalBytesDownloaded = 0;
                var  iterator             = _activity.downloadChunksMap.GetEnumerator();

                do
                {
                    var  entry           = iterator.Current;
                    long timestamp       = entry.Key;
                    long bytesDownloaded = entry.Value;
                    if (currentTimestamp - timestamp > referencePeriod)
                    {
                        //iterator.remove(); remove current item
                    }
                    else
                    {
                        totalBytesDownloaded += bytesDownloaded;
                    }
                } while (iterator.MoveNext());
                float  downloadPeriodSec = downloadPeriod / 1000f;
                long   bytesPerSecond    = (long)Math.Round(totalBytesDownloaded / downloadPeriodSec);
                String formattedTimeLeft = "";

                if (totalBytesDownloaded == 0)
                {
                    formattedTimeLeft = "-";
                }
                else if (resource is MapDownloadResource)
                {
                    MapDownloadResource mapResource = (MapDownloadResource)resource;
                    long remainingBytes             = (mapResource.getSkmAndZipFilesSize() + mapResource.getTXGFileSize()) - mapResource.NoDownloadedBytes;
                    long timeLeft = (downloadPeriod * remainingBytes) / totalBytesDownloaded;
                    formattedTimeLeft = getFormattedTime(timeLeft);
                }

                return(new Tuple <string, string>(convertBytesToStringRepresentation(bytesPerSecond) + "/s", formattedTimeLeft));
            }
            private int getPercentage(DownloadResource downloadResource)
            {
                int percentage = 0;

                if (downloadResource is MapDownloadResource)
                {
                    MapDownloadResource mapDownloadResource = (MapDownloadResource)downloadResource;
                    percentage = (int)(((float)mapDownloadResource.NoDownloadedBytes / (mapDownloadResource.getSkmAndZipFilesSize() + mapDownloadResource.getTXGFileSize())) * 100);
                }
                return(percentage);
            }
            public override View GetView(int position, View convertView, ViewGroup parent)
            {
                ListItem currentItem = this[position];
                View     view        = null;

                if (convertView == null)
                {
                    LayoutInflater inflater = _activity.GetSystemService(Context.LayoutInflaterService) as LayoutInflater;
                    view = inflater.Inflate(Resource.Layout.element_download_list_item, null);
                }
                else
                {
                    view = convertView;
                }

                ImageView      arrowImage            = view.FindViewById <ImageView>(Resource.Id.arrow);
                TextView       downloadSizeText      = view.FindViewById <TextView>(Resource.Id.package_size);
                TextView       downloadNameText      = view.FindViewById <TextView>(Resource.Id.package_name);
                RelativeLayout middleLayout          = view.FindViewById <RelativeLayout>(Resource.Id.middle_layout);
                ImageView      startPauseImage       = view.FindViewById <ImageView>(Resource.Id.start_pause);
                ImageView      cancelImage           = view.FindViewById <ImageView>(Resource.Id.cancel);
                TextView       stateText             = view.FindViewById <TextView>(Resource.Id.current_state);
                ProgressBar    progressBar           = view.FindViewById <ProgressBar>(Resource.Id.download_progress);
                RelativeLayout progressDetailsLayout = view.FindViewById <RelativeLayout>(Resource.Id.progress_details);
                TextView       percentageText        = view.FindViewById <TextView>(Resource.Id.percentage);
                TextView       timeLeftText          = view.FindViewById <TextView>(Resource.Id.time_left);
                TextView       speedText             = view.FindViewById <TextView>(Resource.Id.speed);

                downloadNameText.Text = currentItem.Name;

                if (currentItem.Children == null || currentItem.Children.Count == 0)
                {
                    arrowImage.Visibility = ViewStates.Gone;
                }
                else
                {
                    arrowImage.Visibility = ViewStates.Visible;
                }

                if (currentItem.DownloadResource != null)
                {
                    DownloadResource downloadResource = currentItem.DownloadResource;

                    bool progressShown = downloadResource.DownloadState == SKToolsDownloadItem.Downloading || downloadResource.DownloadState == SKToolsDownloadItem.Paused;
                    if (progressShown)
                    {
                        progressBar.Visibility           = ViewStates.Visible;
                        progressDetailsLayout.Visibility = ViewStates.Visible;
                        progressBar.Progress             = getPercentage(downloadResource);
                        percentageText.Text = getPercentage(downloadResource) + "%";
                        if (downloadResource.DownloadState == SKToolsDownloadItem.Paused)
                        {
                            timeLeftText.Text = "-";
                            speedText.Text    = "-";
                        }
                        else if (_activity.refreshDownloadEstimates)
                        {
                            Tuple <string, string> pair = calculateDownloadEstimates(downloadResource, 20);
                            speedText.Text    = pair.Item1;
                            timeLeftText.Text = pair.Item2;
                            _activity.refreshDownloadEstimates = false;
                        }
                    }
                    else
                    {
                        progressBar.Visibility           = ViewStates.Gone;
                        progressDetailsLayout.Visibility = ViewStates.Gone;
                    }

                    long bytesToDownload = 0;
                    if (downloadResource is MapDownloadResource)
                    {
                        MapDownloadResource mapResource = (MapDownloadResource)downloadResource;
                        bytesToDownload = mapResource.getSkmAndZipFilesSize() + mapResource.getTXGFileSize();
                    }

                    if (bytesToDownload != 0)
                    {
                        middleLayout.Visibility     = ViewStates.Visible;
                        downloadSizeText.Visibility = ViewStates.Visible;
                        downloadSizeText.Text       = convertBytesToStringRepresentation(bytesToDownload);
                    }
                    else
                    {
                        middleLayout.Visibility     = ViewStates.Gone;
                        downloadSizeText.Visibility = ViewStates.Gone;
                    }

                    switch (downloadResource.DownloadState)
                    {
                    case SKToolsDownloadItem.NotQueued:
                        stateText.Text = ("NOT QUEUED");
                        break;

                    case SKToolsDownloadItem.Queued:
                        stateText.Text = ("QUEUED");
                        break;

                    case SKToolsDownloadItem.Downloading:
                        stateText.Text = ("DOWNLOADING");
                        break;

                    case SKToolsDownloadItem.Downloaded:
                        stateText.Text = ("DOWNLOADED");
                        break;

                    case SKToolsDownloadItem.Paused:
                        stateText.Text = ("PAUSED");
                        break;

                    case SKToolsDownloadItem.Installing:
                        stateText.Text = ("INSTALLING");
                        break;

                    case SKToolsDownloadItem.Installed:
                        stateText.Text = ("INSTALLED");
                        break;

                    default:
                        break;
                    }

                    if (downloadResource.DownloadState == SKToolsDownloadItem.NotQueued || downloadResource.DownloadState == SKToolsDownloadItem.Downloading ||
                        downloadResource.DownloadState == SKToolsDownloadItem.Paused)
                    {
                        startPauseImage.Visibility = ViewStates.Visible;
                        if (downloadResource.DownloadState == SKToolsDownloadItem.Downloading)
                        {
                            startPauseImage.SetImageResource(Resource.Drawable.pause);
                        }
                        else
                        {
                            startPauseImage.SetImageResource(Resource.Drawable.download);
                        }
                    }
                    else
                    {
                        startPauseImage.Visibility = ViewStates.Gone;
                    }

                    if (downloadResource.DownloadState == SKToolsDownloadItem.NotQueued || downloadResource.DownloadState == SKToolsDownloadItem.Installing)
                    {
                        cancelImage.Visibility = ViewStates.Gone;
                    }
                    else
                    {
                        cancelImage.Visibility = ViewStates.Visible;
                    }

                    if (downloadResource is MapDownloadResource)
                    {
                        MapDownloadResource mapResource = (MapDownloadResource)downloadResource;
                    }
                }
                else
                {
                    // no download resource
                    downloadSizeText.Visibility      = ViewStates.Gone;
                    middleLayout.Visibility          = ViewStates.Gone;
                    progressBar.Visibility           = ViewStates.Gone;
                    progressDetailsLayout.Visibility = ViewStates.Gone;
                    downloadSizeText.Visibility      = ViewStates.Gone;
                }

                view.Click += (s, e) =>
                {
                    if (currentItem.Children == null || currentItem.Children.Count == 0)
                    {
                        return;
                    }

                    _activity.currentListItems = currentItem.Children;
                    _activity.buildCodesMap();
                    _activity.previousListIndexes.Push(_activity.listView.FirstVisiblePosition);
                    _activity.updateListAndScrollToPosition(0);
                };

                startPauseImage.Click += (s, e) =>
                {
                    if (currentItem.DownloadResource.DownloadState != SKToolsDownloadItem.Downloading)
                    {
                        if (currentItem.DownloadResource.DownloadState != SKToolsDownloadItem.Paused)
                        {
                            activeDownloads.Add(currentItem.DownloadResource);
                            currentItem.DownloadResource.DownloadState = SKToolsDownloadItem.Queued;
                            _activity.appContext.AppPrefs.SaveDownloadQueuePreference(activeDownloads);
                            String destinationPath = _activity.appContext.MapResourcesDirPath + "downloads/";
                            File   destinationFile = new File(destinationPath);
                            if (!destinationFile.Exists())
                            {
                                destinationFile.Mkdirs();
                            }
                            currentItem.DownloadResource.DownloadPath = destinationPath;
                            mapsDAO.updateMapResource((MapDownloadResource)currentItem.DownloadResource);
                        }

                        NotifyDataSetChanged();

                        List <SKToolsDownloadItem> downloadItems;
                        if (!_activity.downloadManager.IsDownloadProcessRunning)
                        {
                            downloadItems = _activity.createDownloadItemsFromDownloadResources(activeDownloads);
                        }
                        else
                        {
                            List <DownloadResource> mapDownloadResources = new List <DownloadResource>();
                            mapDownloadResources.Add(currentItem.DownloadResource);
                            downloadItems = _activity.createDownloadItemsFromDownloadResources(mapDownloadResources);
                        }
                        _activity.downloadManager.StartDownload(downloadItems);
                    }
                    else
                    {
                        _activity.downloadManager.PauseDownloadThread();
                    }
                };

                cancelImage.Click += (s, e) =>
                {
                    if (currentItem.DownloadResource.DownloadState != SKToolsDownloadItem.Installed)
                    {
                        bool downloadCancelled = _activity.downloadManager.CancelDownload(currentItem.DownloadResource.Code);
                        if (!downloadCancelled)
                        {
                            currentItem.DownloadResource.DownloadState     = (SKToolsDownloadItem.NotQueued);
                            currentItem.DownloadResource.NoDownloadedBytes = (0);
                            mapsDAO.updateMapResource((MapDownloadResource)currentItem.DownloadResource);
                            activeDownloads.Remove(currentItem.DownloadResource);
                            _activity.appContext.AppPrefs.SaveDownloadQueuePreference(activeDownloads);
                            NotifyDataSetChanged();
                        }
                    }
                    else
                    {
                        bool packageDeleted = SKPackageManager.Instance.DeleteOfflinePackage(currentItem.DownloadResource.Code);
                        if (packageDeleted)
                        {
                            Toast.MakeText(_activity.appContext, ((MapDownloadResource)currentItem.DownloadResource).getName() + " was uninstalled", ToastLength.Short).Show();
                        }
                        currentItem.DownloadResource.DownloadState     = (SKToolsDownloadItem.NotQueued);
                        currentItem.DownloadResource.NoDownloadedBytes = (0);
                        mapsDAO.updateMapResource((MapDownloadResource)currentItem.DownloadResource);
                        NotifyDataSetChanged();
                    }
                };

                return(view);
            }