# Copyright (c) 2004 Divmod.
# See LICENSE for details.

"""Directory listing."""

# system imports
import os
import stat
try:
	from urllib.parse import quote, unquote
except ImportError:
	# python2 compatibility
	from urllib import quote, unquote

# twisted imports
from nevow import inevow
from nevow import rend
from nevow import loaders
from nevow import tags

def formatFileSize(size):
    if size < 1024:
        return '%ib' % size
    elif size < (1024**2):
        return '%iK' % (size / 1024)
    elif size < (1024**3):
        return '%iM' % (size / (1024**2))
    else:
        return '%iG' % (size / (1024**3))

class DirectoryLister(rend.Page):
    def __init__(self, pathname, dirs=None,
                 contentTypes={},
                 contentEncodings={},
                 defaultType='text/html'):
        self.contentTypes = contentTypes
        self.contentEncodings = contentEncodings
        self.defaultType = defaultType
        # dirs allows usage of the File to specify what gets listed
        self.dirs = dirs
        self.path = pathname
        rend.Page.__init__(self)

    def data_listing(self, context, data):
        from nevow.static import getTypeAndEncoding

        if self.dirs is None:
            directory = os.listdir(self.path)
            directory.sort()
        else:
            directory = self.dirs

        files = []; dirs = []

        for path in directory:
            url = quote(path, '/')
            if os.path.isdir(os.path.join(self.path, path)):
                url = url + '/'
                dirs.append({
                    'link': url,
                    'linktext': path + "/",
                    'type': '[Directory]',
                    'filesize': '',
                    'encoding': '',
                    })
            else:
                mimetype, encoding = getTypeAndEncoding(
                    path,
                    self.contentTypes, self.contentEncodings, self.defaultType)
                try:
                    filesize = os.stat(os.path.join(self.path, path))[stat.ST_SIZE]
                except OSError as x:
                    if x.errno != 2 and x.errno != 13:
                        raise x
                else:
                    files.append({
                        'link': url,
                        'linktext': path,
                        'type': '[%s]' % mimetype,
                        'filesize': formatFileSize(filesize),
                        'encoding': (encoding and '[%s]' % encoding or '')})

        return dirs + files

    def data_header(self, context, data):
        request = context.locate(inevow.IRequest)
        return "Directory listing for %s" % unquote(request.uri)

    def render_tableLink(self, context, data):
        return tags.a(href=data['link'])[data['linktext']]

    def __repr__(self):  
        return '<DirectoryLister of %r>' % self.path
        
    __str__ = __repr__


    docFactory = loaders.stan(tags.html[
      tags.head[
        tags.title(data=tags.directive('header'))[str],
        tags.style['''
          th, .even td, .odd td { padding-right: 0.5em; }
          .even-dir { background-color: #efe0ef }
          .even { background-color: #eee }
          .odd-dir {background-color: #f0d0ef }
          .odd { background-color: #dedede }
          .icon { text-align: center }
          .listing {
              margin-left: auto;
              margin-right: auto;
              width: 50%;
              padding: 0.1em;
              }

          body { border: 0; padding: 0; margin: 0; background-color: #efefef;}
          h1 {padding: 0.1em; background-color: #777; color: white; border-bottom: thin white dashed;}
          ''']
      ],
      tags.body[tags.div(_class='directory-listing')[
        tags.h1(data=tags.directive('header'))[str],
        tags.table(render=rend.sequence, data=tags.directive('listing'))[
          tags.tr(pattern="header")[
            tags.th["Filename"],
            tags.th["Size"],
            tags.th["Content type"],
            tags.th["Content encoding"],
          ],
          tags.tr(_class="even", pattern="item")[
            tags.td[tags.a(render=tags.directive("tableLink"))],
            tags.td(data=tags.directive("filesize"))[str],
            tags.td(data=tags.directive("type"))[str],
            tags.td(data=tags.directive("encoding"))[str],
          ],
          tags.tr(_class="odd", pattern="item")[
            tags.td[tags.a(render=tags.directive("tableLink"))],
            tags.td(data=tags.directive("filesize"))[str],
            tags.td(data=tags.directive("type"))[str],
            tags.td(data=tags.directive("encoding"))[str],
          ]
        ]
      ]]
    ])
