import marked from "marked";
import express from "express"
import ejs from "ejs";
import fs from "fs";
import path from "path";
import jsdom from "jsdom";
import IConfig from "@src/types/Config";
import IPost from "@src/types/Post";

// parse config (cant use require or import because the compiler gets mad)
let config: IConfig = JSON.parse(fs.readFileSync(path.join(__dirname, '../', 'data', 'config.json'), 'utf-8'))

// init app
let app = express();

// set view engine to ejs
app.set("view engine", "ejs")
app.set('views', path.join(__dirname, 'views', 'themes', config.theme))

// html stripper, used for title
async function htmlStripper(html: string){
  return new jsdom.JSDOM(html).window.document.body.textContent || " ";
}

// returns Post array
async function contentScan(): Promise<IPost[]>{
  let posts: IPost[] = []
  let postsDir = path.join(__dirname, '../', 'data',"posts")
  let files = await fs.readdirSync(postsDir).filter((name: string) => name.toLowerCase().endsWith(".md"))
  for (const file of files) {

    let postPath = path.join(postsDir, file)
    let metadata = fs.statSync(postPath)
    let postContent = fs.readFileSync(postPath, "utf-8")

    // Retrieve first line in file, then turn it into html and then strip the html.
    posts.push(
      {
        file: file, 
        title: await htmlStripper(
          await marked.parse(
            postContent.split("\n")[0] 
          )
        ), 
        metadata: metadata,
        parsedPost: await marked.parse(postContent), 
        rawPost: postContent
      }
    )
  }
  return posts;
}

app.get("/", async (req:express.Request,res:express.Response) => {
  // render index.ejs & pass config, and posts.
  res.render(`index`, {posts: (await contentScan()), config: config})
});

// post reader
app.use("/post/:post", async (req:express.Request,res:express.Response) => {

  // check if the post exists
  let pathToPost = path.join(__dirname, '../', 'data', "posts", req.params.post);
  if(!fs.existsSync(pathToPost)) return res.status(404).end();

  // retrieve posts and check for parameter
  let posts = await contentScan();
  let post = posts.filter(post => post.file === req.params.post)
  if(!post[0]) return res.status(404).end()

  // render post using post.ejs. pass all the posts, the post itself and the config
  res.render(`post`, {posts: posts, post: post[0], config: config})
})

app.use('/static', express.static(path.join(__dirname, '../', "static")))
if (config['use_custom_assets']) app.use('/assets', express.static(path.join(__dirname, "../", "data", "assets")));

app.listen(3024)
