# -*- coding: utf-8 -*-


import sys
import os
import subprocess
import urllib
#import zlib
#import bz2
import zipfile
#import tarfile
from optparse import OptionParser


ENV = None
OPTS = None
PATH = None
TARGETS = None
optparser = None


if not hasattr(str, 'format'):
    # Dirty implementation of str.format()
    # Ignores format_spec
    import __builtin__
    import re
    re_format = re.compile('((^{)|([^{]{))(((([a-zA-Z_]\w*)|(\d*))(([.][^.[]+?)|([[][^.[]+?[]]))*?))([!].)?(:[^}]*)?}')
    re_format_field = re.compile('([.][^.[]+)|([[][^.[]+[]]).*')
    class str(__builtin__.str):
        def format(self, *args, **kwargs):
            idx = [0]
            def sub(m):
                start_char = m.group(0)[0]
                if start_char == '{':
                    start_char = ''
                field = m.group(8)
                conversion = m.group(12)
                format_spec = m.group(13)
                if field is None:
                    field = m.group(7)
                    v = kwargs[field]
                else:
                    if field != '':
                        i = int(field)
                    else:
                        i = idx[0]
                        idx[0] += 1
                    v = args[i]
                s = m.group(4)
                s = s[len(field):]
                while s:
                    m = re_format_field.match(s)
                    name = m.group(1)
                    if name is not None:
                        v = getattr(v, name[1:])
                        s = s[len(name):]
                    else:
                        i = m.group(2)[1:-1]
                        s = s[len(i) + 2:]
                        try:
                            i = int(i)
                        except:
                            pass
                        v = v[i]
                if conversion is None or conversion == 's':
                    v = str(v)
                elif conversion == 'r':
                    v = repr(v)
                else:
                    raise ValueError("Unknown conversion character '%s'" % conversion)
                return start_char + v
            s = re_format.sub(sub, self)
            return s.replace('{{', '{').replace('}}', '}')
    __builtin__.str = str


PACKAGE = {
    'title': 'example',
    'desc': 'default description',
}

INDEX = {
    'example': r'''
        <hr/>
<!-- start {name} {{example.{name}._comment_end}}
        <h2 class='title'>{{example.{name}.title}}</h2>
        <h3 class='desc'>{{example.{name}.desc}}</h3>
        <ul class='demos'>
            {{example.{name}.demos}}
        </ul>
{{example.{name}._comment_start}} -->
        <h4 class='source'><a href="{name}/">source directory</a> ({name})<h4>
    ''',
    'demo': r'''
        <li class='demo'>(demo) <a href="{name}/output/{target}.html">{target}</a></li>
    ''',
}


class _e(object):

    _ident = 'example'

    _special = {
        '_comment_start': '<!--',
        '_comment_end': '-->',
    }

    def __init__(self, examples=None, **kwds):
        if examples is None:
            self._examples = kwds
        else:
            self._examples = examples
            self._examples.update(kwds)
        self._path = [self._ident]

    def __repr__(self):
        return '_e(%s)' % repr(self.__str__())

    def __str__(self):
        try:
            curr = self._examples
            for frag in self._path[1:]:
                curr = curr[frag]
        except KeyError:
            if frag in self._special:
                curr = self._special[frag]
            else:
                curr = '{%s}' % '.'.join(self._path)
        self._path[1:] = []
        return curr

    def __getattr__(self, name):
        self._path.append(name)
        return self


def _find_python():
    if sys.version_info[0] == 2 and sys.executable and os.path.isfile(sys.executable):
        return sys.executable
    for python in ('python2', 'python2.7', 'python2.6'):
        try:
            subprocess.call([python, '-c', '"raise SystemExit"'])
            return python
        except OSError:
            pass
    return 'python'


def _list_examples():
    examples = [ 
        example
        for example in os.listdir(ENV['DIR_EXAMPLES'])
        if os.path.isfile(os.path.join(ENV['DIR_EXAMPLES'], example, '__main__.py'))
            and not example.startswith('_')
    ]
    examples.sort()
    return examples


def _process_pyjamas(root):
    lim = 3
    while lim > 0:
        root = os.path.join(root, '..')
        boot = os.path.join(root, 'bootstrap.py')
        if os.path.isfile(boot):
            root = os.path.abspath(root)
            boot = os.path.abspath(boot)
            if sys.platform == 'win32':
                pyjsbuild = os.path.join(root, 'bin', 'pyjsbuild.py')
            else:
                pyjsbuild = os.path.join(root, 'bin', 'pyjsbuild')
            break
        lim = lim - 1
    if lim == 0:
        raise RuntimeError('Unable to locate pyjamas root.')
    # Bootstrap on test failure; attempts to fix a couple issues at once
    null = open(os.devnull, 'wb')
    try:
        if subprocess.call(['python', pyjsbuild], stdout=null, stderr=subprocess.STDOUT) > 0:
            raise OSError
    except OSError:
        subprocess.call(['python', boot], stdout=null, stderr=subprocess.STDOUT)
    return {
        'DIR_PYJAMAS': root,
        'BASE_EXAMPLES': os.path.join(root, 'examples'),
        'BIN_PYJSBUILD': pyjsbuild,
    }


def _process_environ():
    return dict([
        (k[5:], v[:])
        for k, v in os.environ.items()
        if k.startswith('PYJS')
    ])



def _process_args(args):
    return {'ARG_PYJSBUILD': args or ['-O']}


def _process_path(targets, target):
    path = PATH
    if isinstance(targets, dict):
      	if 'path' in targets[target]:
            path = targets[target]['path']
            if not path.startswith(os.sep):
                path = os.path.join(PATH, path)
    return path

def get_optparser(**kwargs):
    global optparser
    if optparser is None:
        optparser = OptionParser(**kwargs)
        add_option = optparser.add_option
        add_option(
            '--download',
            dest='download',
            action='store_true',
            default=False,
            help='permit downloads of files or libraries',
        )
        add_option(
            '--misc',
            dest='misc',
            action='store_true',
            default=False,
            help='build miscellaneous examples',
        )
        add_option(
            '--deprecated',
            dest='deprecated',
            action='store_true',
            default=False,
            help='build deprecated examples',
        )
    return optparser


def init(path):
    global ENV, PATH, OPTS
    optparser = get_optparser()
    opts, args = optparser.parse_args()
    OPTS=opts
    PATH = path
    ENV = {}
    ENV.update(_process_environ())
    ENV.update(_process_args(args))
    if 'BIN_PYTHON' not in ENV:
        ENV['BIN_PYTHON'] = _find_python()
    if 'DIR_PYJAMAS' not in ENV:
        ENV.update(_process_pyjamas(path))
    if 'DIR_EXAMPLES' not in ENV:
        ENV['DIR_EXAMPLES'] = os.path.dirname(path)
    ENV['NAME_EXAMPLE'] = os.path.basename(path)
    ENV['DIR_EXAMPLE'] = path


def download(downloads):
    for download in downloads:
        url = download['url']
        dst = download['dst']
        if not os.path.exists(dst):