﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;


namespace fileList
{
    class Program
    {
        private static StreamWriter myHtmlWriter; //for writing the filelist into an HTML-file
        private static int intFiles = 0; //counter for detected files
        private static int intDirectories = 0; //counter for detected folders
        

        static void Main(string[] args)
        {
            String strErrors = ""; //for collection errors

            if (args.Length < 1) //checks if there are parameters
                strErrors = "There are no Parameters \n";

            foreach (String strParameter in args) //check if the given direcories are avaliable
                if (!System.IO.Directory.Exists(strParameter))
                    strErrors += "The direcory '" + strParameter + "' could not be found! \n"; //directory was not found
            
            if (!strErrors.Equals("")) //if there are errors
            {
                //Print errors to console & wait for any key
                Console.Write("There where some errors: \n" + strErrors + "\nPress any key to exit");
                Console.ReadKey();
                
                //Stop the Programm
                return;
            }
            
            //Parameters are vaild; begin with the fileListing

            foreach (String strParameter in args)
            {
                //Check if there is already a fileList-File in the direcory
                if (System.IO.File.Exists(strParameter + "\\fileList.html"))
                {   //if yes:
                    //Output -> ask if user want to skip or overwrite
                    Console.WriteLine("The File 'fileList.html' does already exist in the direcory '" + strParameter + "'. If you want to skip the process for tat directory press 's'. Otherwise hit any other key ;-)");
                    if (Console.ReadKey().KeyChar.ToString().ToLower().Equals("s"))
                        continue; //skip direcory
                    else //overwrite the file
                        System.IO.File.Delete(strParameter + "\\fileList.html"); //delete file
                }

                //Create a StreamWriter for the Output
                myHtmlWriter = new StreamWriter(strParameter + "\\fileList.html");
                
                //write HTML-Head with Javascript-Stuff
                myHtmlWriter.WriteLine("<html><head><title>FileList for root " + getDirectoryNameByPath(strParameter) + "</title>\n<script type=\"text/javascript\">\n<!--\nfunction toggleLayer( whichLayer )\n{  var elem, vis;\nelem = document.getElementById( whichLayer );\nvis = elem.style;\nif(vis.display=='none'){\nvis.display = 'block';\nelem = document.getElementById( whichLayer + 'Toggle' );\nelem.title = 'Verstecken';\nelem = document.getElementById( whichLayer + 'ToggleDisplay' );\nelem.innerHTML = ' -';\n}\nelse{\nvis.display = 'none';\nelem = document.getElementById( whichLayer + 'Toggle' );\nelem.title = 'Erweitern';\nelem = document.getElementById( whichLayer + 'ToggleDisplay' );\nelem.innerHTML = '+';\n}\n}\n//-->\n</script>\n</head>\n<body><h1>FileList</h1><p>Please note: huge File-Structures will cause a long loading process in your browser! Please be patient and wait a little bit...</p><div id=\"loadingIndicator\"><span style=\"color:red\">LOADING</span></div>");
                
                //Starts the recursive function procedeDirectory
                procedeDirectory(strParameter,strParameter);

                //Write the end of the HTML-file
                myHtmlWriter.WriteLine("<script type=\"text/javascript\">\n<!--\ntoggleLayer('loadingIndicator');\n//-->\n</script></body></html>");

                //Close Writer
                myHtmlWriter.Close();

                //Print the number of files and folders on the console
                Console.WriteLine("\n-------------------------------------\n\n\nWow! There where " + intDirectories + " directories and " + intFiles + " files!\nYou can hit enter do exit ;-)");

                //Wait for Enter to exit
                Console.ReadLine();
            }
        }

        /// <summary>
        /// Lists all files and subdirs as HTML-List Elements. This function will call itself again -> recursive
        /// </summary>
        /// <param name="strDirectory">All Files out of this directory and all subdirs will be listed</param>
        /// <param name="strRoot">The Root-Path for linking the files</param>
        static private void procedeDirectory(String strDirectory, String strRoot)
        {
            //Print an indicator, that programm is still running
            Console.Write('.');

            //Create a GUID to identify the Directory with CSS/DOM/Javascript
            String strGuid = System.Guid.NewGuid().ToString(); 

            //Count up directories
            intDirectories++;

            //Create a HTML-Listelement which can be collapsed
            myHtmlWriter.WriteLine("<li><span id=\"" + strGuid + "ToggleDisplay\">+</span><a class=\"dirName\" id=\"" + strGuid + "Toggle\" href=\"javascript:toggleLayer('" + strGuid + "');\">" + getDirectoryNameByPath(strDirectory) + "</a><ul class=\"dirContent\" id=\"" + strGuid + "\" style=\"display:none\">");

            //Do the same stuff to all subdirs
            foreach (String strSubDirectory in System.IO.Directory.GetDirectories(strDirectory))
            {
                myHtmlWriter.WriteLine("<ul class=\"subDirList\">");
                procedeDirectory(strSubDirectory, strRoot);
                myHtmlWriter.WriteLine("</ul>");
            }

            //Procede all files in the directory
            foreach (String strFile in System.IO.Directory.GetFiles(strDirectory))
            {
                //List every file with an hyperlink to itself
                myHtmlWriter.WriteLine("<li><a href=\"" + getRelativePath(strRoot, strFile) + "\" type=\"application/octet-stream\">" + getDirectoryNameByPath(strFile) + "</a></li>");
                intFiles++;
            }

            //Close the listelement
            myHtmlWriter.WriteLine("</ul></li>");
        }

        /// <summary>
        /// Gets the Foldername for a specific folder.
        /// </summary>
        /// <param name="strPath">Path to folder</param>
        /// <returns>A substring from the path: the foldername</returns>
        static private String getDirectoryNameByPath(String strPath)
        {
            if(strPath.Length > 3 ) //if the Path is not something like "C:\"
                return strPath.Substring(strPath.LastIndexOf('\\') + 1, strPath.Length - strPath.LastIndexOf('\\') - 1); //cut it
            else
                return strPath; //return the whole path
        }

        /// <summary>
        /// Returns the relative path from the filelist-HTML-file to the specific file
        /// </summary>
        /// <param name="strRoot">absolute Rootpath</param>
        /// <param name="strFile">absolute Path to file</param>
        /// <returns>relative path from the filelist-HTML-file to the specific file</returns>
        static private String getRelativePath(String strRoot, String strFile)
        {
            return strFile.Substring(strFile.LastIndexOf(strRoot) + strRoot.Length, strFile.Length - strFile.LastIndexOf(strRoot) - strRoot.Length);
        }
    }
}

