package pages

import (
  "bufio"
  "bytes"
  "gitler.moe/suwako/gitlin/utils"
  "context"
  "encoding/base64"
  htmlfmt "github.com/alecthomas/chroma/v2/formatters/html"
  "github.com/alecthomas/chroma/v2/lexers"
  "github.com/alecthomas/chroma/v2/styles"
  "github.com/carlmjohnson/requests"
  "github.com/gofiber/fiber/v2"
  "html/template"
  "net/http"
  "path/filepath"
)

// FileView is the file view page
func FileView(c *fiber.Ctx) error {
  var file string
  url := "https://raw.githubusercontent.com/" + c.Params("user") + "/" + c.Params("repo") + "/" + c.Params("branch") + "/" + c.Params("+")
  err := requests.
    URL(url).
    ToString(&file).
    Fetch(context.Background())
  if err != nil {
    return c.Status(404).Render("error", fiber.Map{
      "error": err,
      "ver": utils.Ver,
      "ves": utils.Ves,
    })
  }

  ext := filepath.Ext(c.Params("+"))
  // Make an issue for other formats thanks
  if ext == ".jpeg" || ext == ".jpg" || ext == ".png" || ext == ".svg" || ext == ".gif" || ext == ".webp" {
    data := []byte(file)
    dst := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
    base64.StdEncoding.Encode(dst, data)
    dstStr := string(dst)
    // Detect content-type since base64 encoding needs content-type
    mimeType := http.DetectContentType(data)
    if ext == ".svg" {
      mimeType = "image/svg+xml"
    }
    css := `img {
          object-fit: cover;
          width: 100%;
          height: 250px;
        }`
    html := "<img src='data:" + mimeType + ";base64," + dstStr + "' alt=" + c.Params("+") + ">"
    return c.Render("file", fiber.Map{
      "title":      c.Params("+") + " | " + c.Params("user") + "/" + c.Params("repo"),
      "ver":        utils.Ver,
      "ves":        utils.Ves,
      "file":       html,
      "css":        css,
      "fullname":   c.Params("user") + "/" + c.Params("repo"),
      "name":       c.Params("+"),
      "fileBranch": c.Params("branch"),
      "type":       "img",
    })
  }
  lexer := lexers.Match(c.Params("+"))
  if lexer == nil {
    lexer = lexers.Fallback
  }

  formatter := htmlfmt.New(
    htmlfmt.WithClasses(true),
    htmlfmt.WithLineNumbers(true),
    htmlfmt.PreventSurroundingPre(false),
  )

  buf := bytes.Buffer{}
  writer := bufio.NewWriter(&buf)
  style := styles.Get("native")

  tokens, err := lexer.Tokenise(nil, file)
  if err != nil {
    return c.Status(500).Render("error", fiber.Map{
      "error": err,
      "ver": utils.Ver,
      "ves": utils.Ves,
    })
  }
  formatter.Format(writer, style, tokens)

  cssbuf := bytes.Buffer{}
  cssw := bufio.NewWriter(&cssbuf)
  formatter.WriteCSS(cssw, style)

  writer.Flush()
  cssw.Flush()
  return c.Render("file", fiber.Map{
    "title":      c.Params("+") + " | " + c.Params("user") + "/" + c.Params("repo"),
    "ver":        utils.Ver,
    "ves":        utils.Ves,
    "file":       template.HTML(buf.String()),
    "css":        template.CSS(cssbuf.String()),
    "fullname":   c.Params("user") + "/" + c.Params("repo"),
    "name":       c.Params("+"),
    "fileBranch": c.Params("branch"),
    "type":       "code",
  })
}
