#!/usr/bin/env python

import os
import posixpath
import shutil
import sys

from genshi.core import Markup, Stream, START
from genshi.input import HTMLParser
from genshi.output import DocType
from genshi.template import TemplateLoader

basedir = os.path.dirname(os.path.abspath(sys.argv[0]))
templates = TemplateLoader([os.path.join(basedir, 'templates')])

def copyfile(src, dst):
    print 'Copying %s' % os.path.basename(src)
    shutil.copy2(src, dst)

def copytree(src, dst, symlinks=False, skip=()):
    """Recursively copy a directory tree using copy2() (from shutil.copytree.)

    Added a `skip` parameter consisting of absolute paths
    which we don't want to copy.
    """
    names = os.listdir(src)
    os.mkdir(dst)
    errors = []
    for name in names:
        if name in skip:
            continue
        srcname = os.path.join(src, name)
        dstname = os.path.join(dst, name)
        try:
            if symlinks and os.path.islink(srcname):
                linkto = os.readlink(srcname)
                os.symlink(linkto, dstname)
            elif os.path.isdir(srcname):
                copytree(srcname, dstname, symlinks, skip)
            else:
                copyfile(srcname, dstname)
        except (IOError, os.error), why:
            errors.append((srcname, dstname, why))
    if errors:
        raise shutil.Error, errors

def make_relatify(base):
    def relatify(link):
        base_parts = filter(None, base.split('/'))[:-1]
        dest = filter(None, link.split('/'))
        dest_parts = dest[:-1]
        dest_file = dest[-1]
        idx = 0
        for part in base_parts:
            if idx < len(dest_parts) and part == dest_parts[idx]:
                del dest_parts[idx]
            else:
                dest_parts[idx:idx] = ['..']
                idx += 1
        return '/'.join(dest_parts + [dest_file])
    return relatify

def make_document(base, relatify):
    def document(path):
        return Stream(HTMLParser(open(os.path.join(base, path))))
    return document


if __name__ == '__main__':
    destdir = os.path.join(basedir, 'dist')

    if os.path.exists(destdir):
        shutil.rmtree(destdir)

    copytree(os.path.join(basedir, 'resources'), destdir,
             skip=('.DS_Store', '.svn', 'Thumbs.db'))

    pagesdir = os.path.join(basedir, 'pages')
    for root, dirs, files in os.walk(pagesdir):
        if '.svn' in dirs:
            dirs.remove('.svn')
        if '.DS_Store' in files:
            files.remove('.DS_Store')
        if 'Thumbs.db' in files:
            files.remove('Thumbs.db')
        basepath = root[len(pagesdir):].lstrip('/')
        for dirname in dirs:
            os.mkdir(os.path.join(destdir, basepath, dirname))
        for filename in files:
            dirname = root[len(pagesdir):].lstrip('/')
            filepath = os.path.join(root, filename)
            outfile = open(os.path.join(destdir, dirname, filename), 'w')
            try:
                template = templates.load(filepath)
                relpath = posixpath.join(dirname, filename)
                relatify = make_relatify(relpath)
                document = make_document(os.path.join(basedir, 'fragments'),
                                         relatify)
                print 'Generating %s' % relpath
                stream = template.generate(path=relpath, dirname=dirname,
                                           filename=filename, Markup=Markup,
                                           relatify=relatify,
                                           document=document)
                output = stream.render('html', doctype=DocType.HTML_STRICT,
                                       strip_whitespace=False)
                outfile.write(output)
            finally:
                outfile.close()

    copyfile(os.path.join(basedir, 'README.txt'), destdir)


