import httpclient
import os, strutils, strformat, tables, re, sugar, uri

type
  Urls = seq[string]
  Thumbs = seq[string]

proc cacheResources(): Table[string, string] =
  echo "Compiling Resources..."
  var res: Table[string,string]
  for file in walkDir("src/resources"):
    let path =  file.path.split("/")[^1]
    res[path] = staticRead(file.path.replace("src/",""))
  echo "Done"
  return res

const RESOURCES*: Table[string, string] = cacheResources()

proc request(uri: string): string =
  var client = newHttpClient()
  try:
    echo "Requesting ", uri
    let content = client.getContent(uri)
    return content
  except:
    return "Not Found"
  finally:
    client.close()

proc parseUrls(content: string): seq[string] =
  let url_re = re"""<div class="thumb"><a href=\"/video(.*)\">"""
  let urls = collect:
    for url in content.findAll(url_re):
      url.split("\"")[3]
  return urls

proc parseThumbs(content: string): seq[string] =
  let thumb_re = re"""data-src="(.*)""""
  let thumbs = collect:
    for thumb in content.findAll(thumb_re):
      thumb.split("\"")[1]
  return thumbs

proc setUpVideo(content: string, video_uri: string): (string, Urls, Thumbs) = 
  let 
    rel_vids_re = re"""video_related=(.+)"""
    vid_h_url_re = re"""setVideoUrlHigh(.*)"""
    vid_l_url_re = re"""setVideoUrlLow(.*)"""
    vid_hls_re = re"""setVideoHLS(.*)"""
    vid_thumb_re = re"""setThumbUrl(.*)"""
    related_vids = collect:
      for vid in content.findAll(rel_vids_re):
        vid.replace(",","\n")

  var video = content.findAll(vid_h_url_re)[0].split("'")[1]
  let video_low = content.findAll(vid_l_url_re)[0].split("'")[1]
  var video_hls: string
  var video_hls_matches = content.findAll(vid_hls_re)
  if video_hls_matches.len > 0:
    video_hls = video_hls_matches[0].split("'")[1]
  if video == "":
    video = video_low
  let video_thumb = content.findAll(vid_thumb_re)[0].split("'")[1]
  var HTML_VIDEO = fmt"""<center><video poster="{video_thumb}" controls autoplay loop><source src="{video}"/></video></center><center id='infoblock'>"""
  if video_hls != "":
    HTML_VIDEO &= fmt"""<h3>HD Stream: </h3><input type='text' size='50' value='{video_hls}' /><br/>(use with a video player)"""
  HTML_VIDEO &= "</center>"
  var thumbs: Thumbs = @[]
  var urls: Urls = @[]
  for vid in related_vids:
    thumbs = collect:
      for thumb in vid.findAll(re""""i":(.*)"""):
        thumb.replace("\\","").replace("\"i\":","").replace("\"","")
    urls = collect:
      for url in vid.findAll(re""""u":(.*)"""):
        url.replace("\\","").replace("\"u\":","").replace("\"","")
  return (HTML_VIDEO, urls, thumbs)

proc getPagination(content:string): string =
  let page_re = re"""<div class="pagination ">(.*)</div>"""
  let pagination = content.findAll(page_re)
  if pagination.len > 0:
    return pagination[0]

proc compilePage(content: string, video_uri: string = "", search_query: string = ""): string =
  var 
    page: string = ""
    urls: Urls
    thumbs: Thumbs
    pagination: string = getPagination(content)
  page &= RESOURCES["html_start"].replace("**QUERY**",search_query)
  if video_uri != "":
    var video: string
    (video, urls, thumbs) = setUpVideo(content, video_uri)
    page &= fmt"<center>{video}</center>"
  else:
    urls = parseUrls(content)
    thumbs = parseThumbs(content)
  if pagination != "":
    page &= pagination
  page &= "<section>"
  for idx, url in urls:
    var 
      vid_url, vid_thumb: string
    vid_url = url.replace("THUMBNUM","0")
    if thumbs.len > idx:
      vid_thumb = thumbs[idx].replace("THUMBNUM","1")
    else:
      vid_url = url.replace("THUMBNUM","1")
      vid_thumb = thumbs[^1].replace("THUMBNUM","1")
    let title = vid_url.split("/")[^1].replace("_"," ")
    page &= fmt"""<div><a href="{vid_url}"><img src="{vid_thumb}"/><br/>{title}</a></div>"""
  page &= "</section>"
  if pagination != "":
    page &= pagination
  page &= "<style>"
  page &= RESOURCES["css.css"]
  page &= "</style>"
  page &= RESOURCES["html_end"]
  return page

proc compileRSSPage(content: string, search_query: string = ""): string =
  var rss = RESOURCES["rss_start"]
  let urls = parseUrls(content)
  let thumbs = parseThumbs(content)
  for idx, url in urls:
    var 
      vid_url, vid_thumb: string
    vid_url = url.replace("THUMBNUM","0")
    if thumbs.len > idx:
      vid_thumb = thumbs[idx].replace("THUMBNUM","1")
    else:
      vid_url = url.replace("THUMBNUM","1")
      vid_thumb = thumbs[^1].replace("THUMBNUM","1")
    let title = vid_url.split("/")[^1].replace("_"," ")
    rss &= fmt"""<item><title>{title}</titcle><link>{vid_url}</link><description>{title}</description><image><title>{title}</title><url>{vid_thumb}</url></image></item>"""
  rss &= RESOURCES["rss_end"]
  return rss

const XV = "https://www.xvideos.com"
proc findSearchQuery(query: string): string = 
  var search_query: string
  let search = parseUri(query)
  for item in search.query.split("&"):
    let parm = item.split("=")
    if parm[0] == "k":
      search_query = parm[1]
      break
  return search_query

proc genpage*(path: string, video_uri: string = ""): string = 
  let content = request(XV & path)
  let search_query = findSearchQuery(path)
  if video_uri == "":
    return compilePage(content, search_query = search_query)
  else:
    return compilePage(content, video_uri)

proc genRSS*(path: string): string =
  let content = request(XV & path)
  let search_query = findSearchQuery(path)
  return compileRSSPage(content, search_query = search_query)