#White #Dark #txt #download

        
#!/usr/bin/env python3

import argparse

p = argparse.ArgumentParser()
p.add_argument('filename')
p.add_argument('--template')
p.add_argument('--out')

p.add_argument('--langs', nargs='+', default=[])
p.add_argument('--lang')
p.add_argument('--lang-url')
p.add_argument('--id-splitter', default=",")
a = args = p.parse_args()

assert args.template and args.out 
if args.langs:
    assert args.lang in args.langs
if (args.lang or args.lang_url) and not args.langs:
    raise ValueError('when in lang mode, give list of langs !')

assert args.id_splitter != ''

from generate_utils import OutFileGreen as OutFile

import re

def printret(x):
    from pprint import pprint;
    pprint([vars(args), x])
    return x

def slugify(name):
    return name.replace('/', '-').replace(' ', '-')

def replace_markdown(code):
    """
    takes a html escaped python string and replace markdown in one line comments
    # https://google.be => <a href="https://google.be">a link</a>
    # a link => <a href="https://google.be">a link</a>
    # a link => <a href="https://google.be">a link</a>
    
    # will not do the job in triple quote comments
    """
    lines = code.split('\n')
    comment = re.compile('^(.*?#)(.*)$') # this does not work with "#" in strings
    for i,line in enumerate(lines):
        m = comment.match(line)
        if m:
            a,b = m.groups()
            if a.count("'") % 2 == 1 or a.count("'") % 2 == 1:
                continue # we are in a string !
            for x in {'ATTENTION', 'TEST'}:
                b = re.sub(x, lambda m: '<span class="{}">{}</span>'.format(x.lower(), m.group(0)), b)
            b = re.sub('\[([^]]*)\]\(([^)]*)\)', lambda m: '<a class="added" href="{}">{}</a>'.format(m.group(2) or m.group(1), m.group(1) or m.group(2)), b)
            lines[i] = a + b
    return '\n'.join(lines)

def find_para(iterable_of_lines):
    r"""
    >>> from pprint import pprint
    >>> pprint(list(find_para('''\
# Hello
# World

# Let's python
a = 5

world = 2
# wow

# looks nice
b = 2

# Now we do some stuff
# in the house

# That's why we want
# to have fun
    '''.split('\n'))))
    [('para', 'Hello World'),
    ('code', ''),
    ('code', "# Let's python"),
    ('code', 'a = 5\n\nworld = 2'),
    ('code', '# wow'),
    ('code', ''),
    ('code', '# looks nice'),
    ('code', 'b = 2\n'),
    ('para', 'Now we do some stuff in the house'),
    ('code', ''),
    ('para', "That's why we want to have fun"),
    ('code', '    ')]
    """
    from itertools import groupby, chain
    for key, values in groupby(iterable_of_lines, key=lambda x:x.lstrip().startswith('#')):
        if key == False:
            yield 'code', '\n'.join(values)
        else:
            it = iter(values)
            first = next(values)
            second = next(values, None)
            if second == None:
                yield 'code', first
            else:
                yield 'para', ' '.join(_.lstrip().lstrip('#').lstrip() for _ in chain([first, second], values))

def group_filter_para(iterable_of_lines):
    """
    [('para', 'Hello World'),
    ('code', ''),
    ('code', "# Let's python"),
    ('code', 'a = 5\n\nworld = 2'),
    ('code', '# wow'),
    ('code', ''),
    ('code', '# looks nice'),
    ('code', 'b = 2\n'),
    ('para', 'Now we do some stuff in the house'),
    ('code', ''),
    ('para', "That's why we want to have fun"),
    ('code', '    ')]
    ->
    [('para', 'Hello World'),
    ('code', "\n# Let's python\na = 5\n\nworld = 2\n# wow\n\n# looks nice\nb = 2\n"),
    ('para', 'Now we do some stuff in the house'),
    ('para', "That's why we want to have fun")]
    """
    from itertools import groupby, count
    C = count()
    return [
        (a,b) for a,b in (
            (('code' if a == 'code' else 'para'), '\n'.join(b[1] for b in b))
            for a,b in groupby(
                find_para(iterable_of_lines),
                key=lambda x:('code' if x[0] == 'code' else str(next(C)))))
        if b.strip()
    ]
    
    # other implementation
    # L = list(find_para(iterable_of_lines))
    #def rnext(default, iterable):
        #return next(iterable, default)
    
    ## code+ -> code
    #i = 1
    #while i < len(L):
        #if L[i][0] == 'code' == L[i-1][0]:
            #j = rnext(len(L), (j for j in range(i-1, len(L)) if L[j][0] != 'code'))
            #L[i-1:j] = [('code', '\n'.join(L[x][1] for x in range(i-1,j)))]
        #i += 1
    
    ### remove empty code 
    #i = 0
    #while i < len(L):
        #if L[i][0] == 'code' and not L[i][1].strip():
            #del L[i]
        #else:
            #i += 1
    
    #return L

with open(args.filename) as f:
    c = replace_markdown(f.read())
    L = c.split('\n')
    # L = [l.strip('\n') for l in f]

# remove comment line or empty at the beginning
while L and re.compile(r'\s*#?').match(L[0]).group(0) != '':
    del L[0]

if L[0].startswith('"""') or L[0].startswith("'''"):
    sep = '"""' if L[0].startswith('"""') else "'''"
    txt = L[0][3:]
    i = 1
    try:
        while sep not in L[i]:
            txt += L[i] + '\n'
            i += 1
        txt += L[i][:L[i].find(sep)]
    except IndexError:
        pass
    
    def split_head_body(txt):
        empty = re.compile('^\s*$')
        d = txt.split('\n')
        while d and empty.match(d[0]):
            del d[0]
        while d and empty.match(d[-1]):
            del d[-1]
        i = next(
            (i for i,l in enumerate(d)
             if empty.match(l)),
            None)
        if i is None:
            return '', txt 
        else:
            a,b = '\n'.join(d[:i]), '\n'.join(d[i+1:])
            return ('', a) if empty.match(b) else (a,b)
    title, description = split_head_body(txt)
else:
    title, description = '', ''
    i = 0

sections_info = []
while i < len(L):
    if (L[i].startswith('##')
        and ((i+1) < len(L) and L[i+1].startswith('#'))
        and ((i+2) < len(L) and L[i+2].startswith('##'))):
        # the three conditions are met, we have a section
        section_name = L[i+1].strip('#').strip()
        section_id_base = (L[i].strip('#').strip() + ' ' + L[i+2].strip('#').strip()).strip()
        section_ids = [a.strip() for a in section_id_base.split(args.id_splitter)]  # id_splitter defaults to ','
        if section_ids == ['']:
            section_ids = []
        section_ids = [slugify(section_name) if x == '+' else x for x in section_ids]  # the user can write "+" to keep the orginal slug
        sections_info.append((i+2, section_name, section_ids))
        i = i + 3
    else:
        i = i + 1

sections = []
for i, (n1, name, sids) in enumerate(sections_info):
    rang = range(
        n1 + 1,
        sections_info[i+1][0]-2 if (i+1) < len(sections_info) else len(L))
    
    block_info_1 = [
        (j, L[j][2:].strip())
        for j in rang if L[j].startswith('##')
    ]
    
    block_info = [
        (name, range(j+1, j2))
        for (j, name), (j2, name2) in zip(block_info_1, block_info_1[1:])
    ]
    
    if block_info_1:
        block_info.append(
            (block_info_1[-1][1], range(block_info_1[-1][0]+1, rang.stop))
        )
    
    if len(block_info) == 0:
        block_info.append(
            ('', rang)
        )
    else:
        block_info.insert(0,
            ('', range(rang.start, block_info[0][1].start-1))
        )
    
    block_info = [
        (name, rang)
        for name, rang in block_info
        if rang # remove empty rang
    ]
    
    section_id = sids[0] if sids else slugify(name)
    sections.append({
        'name': name,
        'id': section_id,
        'other_ids': sids[1:],
        'blocks': [
            {
                'name': block_name,
                'id': section_id + '-' + str(i+1),
                'title': '',
                'description': '',
                'elements': [
                    {'is_code': type == 'code',
                     'is_p': type == 'para',
                     'data': data}
                    for type, data in group_filter_para(L[i] for i in block_range)
                ],
            }
            for i,(block_name, block_range) in enumerate(block_info)
        ],
    })

from django.conf import settings

settings.configure(TEMPLATES=[
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['.'], # if you want the templates from a file
        'APP_DIRS': False, # we have no apps
    },
])

without_extension = lambda x: '.'.join(x.split('.')[:-1]) if '.' in x else x

import django
django.setup()

from django.template import loader
t2 = loader.get_template(args.template)
with OutFile(args.out) as f:
  f.write(t2.render({
    'lang': args.lang or '',
    'download_link': args.filename,
    'name': without_extension(args.filename),
    'title': title,
    'description': description,
    'other_langs': [
        {
            'filename': args.lang_url.format(lang=l),
            'lang': l,
            'text': 'English here!' if l == 'en' else 'Français ici!' if l == 'fr' else 'Lol',
        }
        for l in args.langs
        if args.lang != l
    ],
    'sections': sections,
  }))