const express = require("express");
const path = require("path");
const fs = require("fs");
const app = express();

// Initial Listing Directory
const listingPath = path.join(__dirname, "public");

// index.html path
const indexPath = path.join(__dirname,  "index.html");

// Placeholder in your index.html file where dynamic content will be inserted
const dynamicContentPlaceholder = "<!-- Dynamic Content Placeholder -->";

// Function to read the content of the existing "index.html" file
function readIndexFile() {
	return fs.readFileSync(indexPath, "utf-8");
}

// For any path..
app.get("*", (req, res) => {
	
  const decodedPath = decodeURIComponent(req.path);
  const filePath = path.join(listingPath, decodedPath);

  // Extract the parent directory
  const parentDirectory = path.join(req.path, '../');

  // Return nothing if path does not exist
  if (!fs.existsSync(filePath)) {
    return res.status(404).end();
  }

  // If details of a file directory are returned, create path
  if (fs.statSync(filePath).isDirectory()) {
	// Read contents of directory
    const filesInDir = fs.readdirSync(filePath);
	// For each file in the directory
	// (1) Encode URI for hyperlinks
	// (2) Create HTML for that link
    const links = filesInDir.map(file => {
		const encodedFile = encodeURIComponent(file);
		const fileLink = path.join(req.path, encodedFile);
		
		let linkAttributes = "";
		let fileLocationEncoding = ""
		let convertedString = fileLink.replace(/\\/g, '/');
		let icon = ''

		// Check if the file is of a specific type that should open in a new window/tab
		const fileExtension = path.extname(file).toLowerCase();
		if (isFileTypeToOpenInNewTab(fileExtension)) {
			fileLocationEncoding = 'http://localhost:3000/' + convertedString
			linkAttributes = `onclick="window.open('${fileLocationEncoding}', 'fileWindow', 'width=600,height=400');"`;
			icon = getFileIcon(fileExtension, decodeURIComponent(convertedString))
			return `<div class='file' ${linkAttributes}>
						${icon}
						<span class='info-name'>${file}</span>
					</div>`;
		} else {
			return `<a href="${fileLink}" ${linkAttributes}><div class='folder'><img src='/icons/folder.gif'><span class='info-name'>${file}</span></div></a>`;
		}
	  
		
	  });

    // Read the content of the existing "index.html" file
    const indexContent = readIndexFile();

    // Replace the placeholder with the dynamically generated content
    const finalHtml = indexContent.replace(dynamicContentPlaceholder, 
		`<div class='index-cont'><span class='index-txt'>Index of ${decodeURIComponent(req.path)}</span>
			<a class='return-cont' href='${parentDirectory === '/' ? '/' : parentDirectory}'>
				<img src='/icons/back.png'>
				<span> Parent Directory </span>
			</a>
			<span class='line-break'></span>
		</div>
		<div class='main-cont'>${links.join("")}</div>`);

    // Send the modified content as a response
    return res.send(finalHtml);

  } else {

	// If its a 'file' type, then open it in a new window
    const fileExtension = path.extname(filePath).toLowerCase();

    if (fileExtension === ".pdf") {
      // For PDF files, send the file to be displayed in the browser.
      const fileStream = fs.createReadStream(filePath);
      fileStream.pipe(res);
    } else if(fileExtension === ".mp4") {
		const fileStream = fs.createReadStream(filePath);
		res.set("Content-Type", "video/mp4");
		fileStream.pipe(res);
	} else if(fileExtension === ".docx") {
		const fileStream = fs.createReadStream(filePath);
		res.set("Content-Type", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
		fileStream.pipe(res);
	} else {
      // For other file types, set content type and send file.
      const contentType = getContentType(fileExtension);
      res.set("Content-Type", contentType);
      return res.sendFile(filePath);
    }
  }
});

// Set file icon
function getFileIcon(fileExtension, filePath){
	switch (fileExtension) {
		case ".txt":
			return "<img src='/icons/generic.gif'>";
		case ".png":
			return `<img src="${filePath}" alt="${path.basename(filePath)}" class="thumbnail" />`;
		case ".jfif":
		case ".jpeg":
		case ".jpg":
			return `<img src="${filePath}" alt="${path.basename(filePath)}" class="thumbnail" />`;
		case ".gif":
			return `<img src="${filePath}" alt="${path.basename(filePath)}" class="thumbnail" />`;
		case ".pdf":
		case ".odt":
		case ".docx":
			return "<img src='/icons/text.png'>"
		case ".mp4":
			return "<img src='/icons/movie.gif'>"
		default:
			return "<img src='/icons/unknown.gif'>";
		}
}

// Function to get content type based on file extension
function getContentType(fileExtension) {
  switch (fileExtension) {
    case ".txt":
      return "text/plain";
    case ".png":
      return "image/png";
	case ".jpg":
	  return "image/jpg";
	case ".jpeg":
	  return "image/jpeg";
	case ".jfif":
	  return "image/jpeg";
	case ".gif":
	  return "image/gif";
	case ".mp4":
	  return "video/mp4";
	case ".odt":
	  return "application/vnd.oasis.opendocument.text"
	case ".docx":
	  return "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
    default:
      return "application/octet-stream";
  }
}

// Function to check if the file type should open in a new window/tab
function isFileTypeToOpenInNewTab(fileExtension) {
	const supportedFileTypes = [".pdf", ".png", ".txt", ".mp4", ".jpg", ".jfif", ".gif", ".jpeg", ".odt", ".docx"]; // Add more file types as needed
	return supportedFileTypes.includes(fileExtension);
  }

const PORT = 3000;
app.listen(PORT, () => {
  console.log("Server is running on http://localhost:" + PORT);
});
