#!/usr/bin/env python
#

"""
gls: graphterm-aware ls
"""

import mimetypes
import os
import random
import sys
import xml.dom.minidom
from optparse import OptionParser

import gterm

SPECIAL_FILES = set(["..", ".", "~"])

gbrowsecmd = gterm.env("BROWSE_CMD", "") or "gbrowse"
gimagecmd = gterm.env("IMAGE_CMD", "") or "gimage"
glscmd = gterm.env("LS_CMD", "") or "gls"
gopencmd = gterm.env("OPEN_CMD", "") or "gopen"
gvicmd = gbrowsecmd if gterm.Export_host else gterm.env("VI_CMD", "") or "gvi"

NB2CMD = {"py": "python -i $"+gterm.GT_PREFIX+"DIR/bin/gpylab.py",
          "ipynb": "python -i $"+gterm.GT_PREFIX+"DIR/bin/gpylab.py",
          "js": "node %[notebook]",
          "R": "R -q %[notebook]> |+ ",
          "sh": " %[notebook]",
          }

GENERIC_ICON = "/_static/images/tango-text-x-generic-template.png"

FILE_TYPES = {"directory": ("/_static/images/tango-folder.png", "cd %(path); "+glscmd+" -f"),
              "executable": ("/_static/images/tango-application-x-executable.png", ""),
              "audiofile": ("/_static/images/tango-audio-x-generic.png", gbrowsecmd),
              "htmlfile": ("/_static/images/tango-text-html.png", gopencmd),
              "imagefile": ("/_static/images/tango-image-x-generic.png", gimagecmd),
              "textfile": ("/_static/images/tango-text-x-generic.png", gvicmd),
              "videofile": ("/_static/images/tango-video-x-generic.png", gopencmd),  # Need to implement streaming...
              "pdffile": (GENERIC_ICON, gbrowsecmd),
              "plainfile": (GENERIC_ICON, gopencmd),
}

IMGFORMAT = '<td><a id="glsimg%(id)s" class="gterm-link gterm-imglink %(classes)s" href="%(fileurl)s" data-gtermmime="x-graphterm/%(filetype)s" data-gtermcmd="%(filecmd)s"><img class="gterm-img" src="%(fileicon)s"></img></a>'

TXTFORMAT = '<td><a id="glstxt%(id)s" class="gterm-link %(classes)s" href="%(fileurl)s" data-gtermmime="x-graphterm/%(filetype)s" data-gtermcmd="%(filecmd)s">%(filename)s</a>'

DLOADFORMAT = '<td><a id="glstxt%(id)s" class="gterm-link gterm-download %(classes)s" href="%(fileurl)s" download="%(filebase)s">%(filename)s</a>'

Home_dir = os.path.expanduser("~")
Work_dir = os.getenv("PWD", "") or os.getcwd()
Parent_dir, dir_name = os.path.split(Work_dir)

Special_dirs = [(Parent_dir, ".."),
                (Work_dir, "."),
                (Home_dir, "~")]

Id_prefix = "1%09d" % random.randrange(0, 10**9)
Id_count = 0

def file2html(filepath, filename, filemode=0):
    global Id_count;
    mimetype = None
    fileicon = GENERIC_ICON
    filecmd = ""
    filetype = ""
    filebase = ""
    if filename in SPECIAL_FILES:
        filetype = "directory"
    elif os.path.isdir(filepath):
        filetype = "directory"
    elif os.path.lexists(filepath):
        filebase = os.path.basename(filepath)
        prefix, ext = os.path.splitext(filebase)
        langext = ""
        if ext in (".ipynb", ".json"):
            if ext != ".ipynb":
                prefix, ext = os.path.splitext(prefix)
            if ext == ".ipynb":
                filecmd = NB2CMD["ipynb"]
                filetype = "ipynb"
        elif ext in (".gnb", ".md") or (ext == ".txt" and prefix.endswith(".gnb")):
            if ext != ".gnb":
                prefix, ext = os.path.splitext(prefix)
            if ext == ".gnb":
                prefix, langext = os.path.splitext(prefix)
                langext = langext[1:]
            elif ext in (".py", ".R",):
                langext = ext[1:]
            if langext:
                filecmd = NB2CMD.get(langext,"")
                if filecmd:
                    filetype = langext+"nb"

        if not filetype:
            mimetype, encoding = mimetypes.guess_type(filename)
            if mimetype:
                if mimetype.startswith("audio/"):
                    filetype = "audiofile"
                elif mimetype == "text/html":
                    filetype = "htmlfile"
                elif mimetype.startswith("image/"):
                    filetype = "imagefile"
                elif mimetype == "application/pdf":
                    filetype = "pdffile"
                elif mimetype.startswith("text/") or mimetype == "application/javascript":
                    filetype = "textfile"
                elif mimetype.startswith("video/"):
                    filetype = "videofile"
            if not filetype:
                if os.access(filepath, os.X_OK):
                    filetype = "executable"
                else:
                    filetype = "plainfile"
    else:
        return "", ""

    classes = "droppable" if filetype in ("directory", "executable") else ""
    if not filecmd:
        fileicon, filecmd = FILE_TYPES[filetype]

    fileurl = gterm.get_file_url(filepath, relative=(filetype != "htmlfile"))
    if options.images and mimetype and mimetype.startswith("image/"):
        fileicon = fileurl

    Id_count += 1;
    params = {"classes": classes, "fileurl": fileurl, "filename": filename, "filebase": filebase,
              "filetype": filetype, "fileicon": fileicon, "filecmd": filecmd, "id": Id_prefix+"-"+str(Id_count)}
    
    return IMGFORMAT % params, DLOADFORMAT % params if options.download and params["filebase"] else TXTFORMAT % params

def files2html(file_list, ncols=4):
    rows = []
    rowimg = []
    rowtxt = []

    for j, fileinfo in enumerate(file_list):
        if len(fileinfo) == 2:
            fpath, fname, fsize, ftime, fmode, fuid, fgid = fileinfo[0], fileinfo[1], 0, 0, 0, 0, 0
        else:
            fpath, fname, fsize, ftime, fmode, fuid, fgid = fileinfo
        cellimg, celltxt = file2html(fpath, fname, fmode)
        rowimg.append(cellimg)
        rowtxt.append(celltxt)
        if rowtxt and (not ((j+1) % ncols) or (j+1 == len(file_list))):
            rows.append( '<tr class="gterm-rowimg">' + "".join(rowimg) )
            rows.append( '<tr class="gterm-rowtxt">' + "".join(rowtxt) )
            rowimg = []
            rowtxt = []

    return "\n".join(rows)

def get_file_info(filename):
    filename = os.path.expanduser(filename)
    filepath = os.path.normcase(os.path.normpath(os.path.join(Work_dir, filename)))
    if filename.startswith(".."):
        filename = filepath
    if os.path.exists(filepath):
        fstat = os.stat(filepath)
    elif os.path.lexists(filepath):
        fstat = os.lstat(filepath)
    else:
        return (filepath, filename, 0, 0, 0, 0, 0)
    return (filepath, filename, fstat.st_size, fstat.st_mtime, fstat.st_mode, fstat.st_uid, fstat.st_gid)


usage = "usage: %prog [-f] <location>"
parser = OptionParser(usage=usage)
parser.add_option("-f", "--fullpage",
                  action="store_true", dest="fullpage", default=False,
                  help="Fullpage display")
parser.add_option("-a", "--all",
                  action="store_true", dest="all", default=False,
                  help="Display all files, including hidden")
parser.add_option("-d", "--download",
                  action="store_true", dest="download", default=False,
                  help="Display clickable file links for downloading")
parser.add_option("-i", "--images",
                  action="store_true", dest="images", default=False,
                  help="Display image files as thumbnails")
parser.add_option("-s", "--size",
                  action="store_true", dest="size", default=False,
                  help="Sort by file size")
parser.add_option("-t", "--time",
                  action="store_true", dest="time", default=False,
                  help="Sort by time modified")

(options, args) = parser.parse_args()

if not args:
    args = os.listdir(Work_dir)
    if not options.all:
        args = [x for x in args if not x.startswith(".")]

File_list = [get_file_info(filename) for filename in args]

if options.size:
    File_list.sort(key=lambda x:x[2])
elif options.time:
    File_list.sort(key=lambda x:x[3])
else:
    File_list.sort(key=lambda x:x[1])

try:
    lines = int(os.getenv("LINES"))
    columns = int(os.getenv("COLUMNS"))
except Exception:
    lines = 24
    columns = 80

max_width = max([7]+[len(fileinfo[1]) for fileinfo in File_list])
ncols = max(1, columns // (max_width+1))

Table_list = ['<table frame=none border=0>',
              '<colgroup colspan=%d width=1*>' % (ncols,),
              ]

Table_list.append(files2html(Special_dirs, ncols))
Table_list.append(files2html(File_list, ncols))

Table_list.append('</table>')

html = "\n".join(Table_list) + "\n"

gterm.write_pagelet(html, display=("fullpage" if options.fullpage else "block"), dir=Work_dir)

