// Populates content in a learning unit, which is like a folder but with a tree-like navigation
        // and content is generally displayed in iframes to the right.
        public void PopulateLearningUnit(BbContentDirectory folder)
        {
            string pageSource = http.DownloadString(folder.Url.AbsoluteUri);
            // Get the link to the next content item in a learning unit by following the next arrow link
            // until there are no more left.
            Uri      nextURL = folder.Url;
            HtmlNode nextLink;

            while (nextURL != null)
            {
                populateProgress.AppendStatus(".");
                string          contentSource = http.DownloadString(nextURL);
                List <HtmlNode> contentLinks  = HTMLParser.GetLearningUnitContent(contentSource);
                // for each content link found, add a file. Usually only one
                foreach (HtmlNode link in contentLinks)
                {
                    Uri    contentURL = new Uri(folder.Url, link.Attributes["href"].Value);
                    string linkType   = HTMLParser.GetLinkType(contentURL);
                    string linkName   = HTMLParser.GetLinkText(link);
                    if (linkName == "DefaultText")
                    {
                        linkName = HTMLParser.GetPageTitle(contentSource);
                    }
                    folder.AddFile(new BbContentItem(linkName, contentURL, folder, linkType));
                }
                if (contentLinks.Count == 0) // if no content links found, look for content source in iFrame
                {
                    string iFrameLink = HTMLParser.GetLearningUnitIFrame(contentSource);
                    if (iFrameLink != null)  // if iframe found
                    {
                        Uri    contentURL = new Uri(folder.Url, iFrameLink);
                        string linkType   = HTMLParser.GetLinkType(contentURL);
                        string linkName   = HTMLParser.GetPageTitle(contentSource);
                        folder.AddFile(new BbContentItem(linkName, contentURL, folder, linkType));
                    }
                }
                nextLink = HTMLParser.GetNextLearningUnitContent(contentSource);
                if (nextLink == null)
                {
                    nextURL = null;
                }
                else
                {
                    nextURL = new Uri(folder.Url, nextLink.Attributes["href"].Value);
                }
            }
        }
        // Used recursively to populate all subfolders of a module
        public void PopulateContentDirectory(BbContentDirectory folder)
        {
            string          pageSource   = http.DownloadString(folder.Url.AbsoluteUri);
            List <HtmlNode> contentLinks = HTMLParser.GetContentLinks(pageSource);

            if (contentLinks == null)
            {
                return;
            }
            foreach (HtmlNode link in contentLinks)
            {
                //Console.WriteLine("Adding " + folder.Name + ": " + link.InnerText);
                populateProgress.AppendStatus(".");
                Uri linkURL = new Uri(folder.Url, link.Attributes["href"].Value);
                if (HTMLParser.IsSubFolder(link))   // content is a subfolder
                {
                    BbContentDirectory subFolder = new BbContentDirectory(link.InnerText, linkURL, folder);
                    if (!folder.SubFolders.Contains(subFolder))
                    {
                        folder.AddSubFolder(subFolder);
                    }
                    PopulateContentDirectory(subFolder);
                }
                else if (HTMLParser.IsLearningUnit(link)) //content is a learning unit
                {
                    BbContentDirectory subFolder = new BbContentDirectory(link.InnerText, linkURL, folder);
                    if (!folder.SubFolders.Contains(subFolder))
                    {
                        folder.AddSubFolder(subFolder);
                    }
                    PopulateLearningUnit(subFolder);
                }
                else        // content is a file
                {
                    string        linkType = HTMLParser.GetLinkType(linkURL);
                    BbContentItem newFile  = new BbContentItem(link.InnerText, linkURL, folder, linkType);
                    if (!folder.Files.Contains(newFile))
                    {
                        folder.AddFile(newFile);
                    }
                }
            }
        }
        // Create BbModule objects for each module found and add them to webData
        // Does not populate content within the module
        public void PopulateModules()
        {
            NameValueCollection reqParams = new NameValueCollection();

            reqParams.Add("action", "refreshAjaxModule");
            reqParams.Add("modId", MODID);
            reqParams.Add("tabId", "_1_1");
            reqParams.Add("tab_tab_group_id", "_1_1");
            byte[]          pageSourceBytes = http.UploadValues(PORTAL + "/webapps/portal/execute/tabs/tabAction", "POST", reqParams);
            string          pageSource      = Encoding.UTF8.GetString(pageSourceBytes);
            List <HtmlNode> moduleLinks     = HTMLParser.GetModuleLinks(pageSource);

            foreach (HtmlNode link in moduleLinks)
            {
                // for each module link found, create and add a new module
                Uri      moduleURL = new Uri(new Uri(PORTAL), link.Attributes["href"].Value);
                BbModule newModule = new BbModule(link.InnerHtml, moduleURL);
                if (!webData.Modules.Contains(newModule))
                {
                    webData.AddModule(newModule);
                }
            }
        }