
import regex
import datetime
import os
from pathlib import Path

# slices the part of my_str that starts with sub and returns it
def slicer(my_str,sub):
   index = my_str.find(sub)
   if index !=-1 :
         return my_str[index:] 
   else :
         raise Exception('Sub string not found!')

# remove \kernDIMEN strings and other silly things
def remove_kern_etc(latex_content):
    pattern = r'\\kern-*\d*\.?\d*(em|mm|pt|pc|ex|cm|in|bp|dd|cc|sp)'
    latex_content = regex.sub(pattern, '', latex_content)
    pattern = r'\\markboth\{(.*?)\}\{(.*?)\}'
    latex_content = regex.sub(pattern, '', latex_content)
    return latex_content
    

# replace LaTeX character acronyms with Unicode characters
def replace_latex_chars(html_content):
    replacements = {
        r',,': '„',
        r'``(?=\s)': r'&ldquo;',
    }
    for pattern, replacement in replacements.items():
        html_content = html_content.replace(pattern, replacement)
    return html_content

# replace chars like "a with ä etc.
def replace_accented_chars(html_content):
    # Define a dictionary mapping characters to their accented counterparts
    char_map = {
        'a': 'ä',
        'o': 'ö',
        'u': 'ü',
        'A': 'Ä',
        'O': 'Ö',
        'U': 'Ü',
        's': 'ß'
    }
    
    # Build a regular expression pattern to match the characters you want to replace
    pattern = '(?<!=)"([aouAOUs]{1})'
    
    # Define a function to handle the replacement
    def replace(match):
        char = match.group(1)
        if char in char_map:
            return char_map[char]
        else:
            return match.group(1)
    
    # Use regex.sub to perform the replacement
    result = regex.sub(pattern, replace, html_content)
    return result


# returns for ugly date format yearint-monthint-dayint the German two letters weekday
def get_week_day(uglydate):
    dat = uglydate.split('-')
    try:
        day = datetime.datetime(int(dat[0]), int(dat[1]), int(dat[2])).strftime("%w")
        days = ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa']
        return days[int(day)]
    except:
        print(f"Conversion of uglydate failed: {uglydate} does not seem to be a proper date.")
        return "DATE-ERROR"

# returns the roman month figure for ugly date format
def get_roman_month(uglydate):
    dat = uglydate.split('-')
    months = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI', 'XII']
    try:
        return months[int(dat[1])-1]
    except: 
        print(f"Conversion of uglydate failed: {uglydate} does not seem to be a proper date.")
        return "DATE-ERROR"
# reverses the whole thing and returns an arabic figure for a roman months figure
def get_arabic_month(romanmonth):
    if regex.search('\\d', romanmonth): return int(romanmonth)
    arabicmonth = 0
    months = {'I': 1, 'II': 2, 'III': 3, 'IV': 4, 'V': 5, 'VI': 6, 'VII': 7, 'VIII': 8, 'IX': 9, 'X': 10, 'XI': 11, 'XII': 12}
    if romanmonth in months: return months[romanmonth]
    print(f'WARNING: no proper month id: {romanmonth}')
    return arabicmonth

# transfers the ugly date format into a nice German date format with weekdays and roman month figures
def nice_date(uglydate):
    dat = uglydate.split('-')
    try:
        return f'{get_week_day(uglydate)} {dat[2]}. {get_roman_month(uglydate)}. {dat[0]}'
    except:
        print(f"Conversion of uglydate failed: {uglydate} does not seem to be a proper date.")
        return "DATE-ERROR"

# transfers the ugly date format into the date format of Carnap's diaries
def make_date(uglydate, entrytype='normal'):
    if uglydate == '':
        return uglydate
    dat = uglydate.split('-')
    try:
        date = datetime.datetime(int(dat[0]), int(dat[1]), int(dat[2]))
        if entrytype == 'llong' or date.strftime('%j') == '001':
            return f'{get_week_day(uglydate)} {dat[2]}. {get_roman_month(uglydate)}. {dat[0]}'
        elif entrytype == 'long' or date.strftime('%d') == '01':
            return f'{get_week_day(uglydate)} {dat[2]}. {get_roman_month(uglydate)}.'
        else:
            return f'{get_week_day(uglydate)} {dat[2]}'
    except: 
        print(f"Conversion of uglydate failed: {uglydate} does not seem to be a proper date.")
        return "DATE-ERROR"

# parses an argument of the latex command \diaryref{TB[T]-DAY-MONTH-YEAR}
def parse_date(diarystring):
    uglydate = ""
    if diarystring == "":
        return diarystring
    dat = diarystring.split('-')
    if len(dat) == 4:
        date = f'{dat[3]}-{get_arabic_month(dat[2])}-{dat[1]}'    
        return date
    return uglydate

# transfers the ugly date to the Format ROMANMONTH/YEAR
def make_month(uglydate):
    dat = uglydate.split('-')
    try:
        return f'{get_roman_month(uglydate)}&#8201;/&#8201;{dat[0]}'
    except: 
        print(f"Conversion of uglydate failed: {uglydate} does not seem to be a proper date.")
        return "DATE-ERROR"

# adds labels and counters to notes
def add_all_to_notes(html_content):
    html_content = replace_tag(html_content, 'note-e')
    html_content = replace_tag_alph(html_content, 'note-a', 'a')
    html_content = replace_tag_alph(html_content, 'note-e-inner', 'A')
    html_content = replace_tag_symbols(html_content, 'fn-c')
    return html_content

# adds labels and counters to notes chapterwise
def add_all_to_notes_chapterwise(html_content):
    chapters = html_content.split('<h1')
    i = 0
    while i < len(chapters):
        chapters[i] = add_all_to_notes(chapters[i])
        i += 1
    html_content = '<h1'.join(chapters)
    return html_content

# adds in html_content to each tag_name-tag -label and -content tags, numbering ints
def replace_tag(html_content, tag_name):
    # Define a counter starting from 1
    counter = 1
    # Define a pattern to match <tag_name>ANYTEXT</tag_name>
    pattern = fr'<{tag_name}>(.*?)<\/{tag_name}>'
    # Replace occurrences of <note-e>ANYTEXT</note-e> with <note-e><note-e-label>n</note-e-label>ANYTEXT</note-e>
    def repl(match):
        nonlocal counter
        replacement = f'<{tag_name}><{tag_name}-label data-fn="id{tag_name}{counter}">{counter}</{tag_name}-label><{tag_name}-content  data-fn="id{tag_name}{counter}">{match.group(1)}</{tag_name}-content></{tag_name}>'
        counter += 1
        return replacement
    html_content = regex.sub(pattern, repl, html_content)
    return html_content

# adds in html_content to each tag_name-tag -label and -content tags, numbering a, ... oder A, ...
def replace_tag_alph(html_content, tag_name, start):
    # Define a counter starting from 1
    counter = start
    metacounter = 1
    # Define a pattern to match <tag_name>ANYTEXT</tag_name>
    pattern = fr'<{tag_name}>(.*?)<\/{tag_name}>'
    # Replace occurrences of <note-e>ANYTEXT</note-e> with <note-e><note-e-label>n</note-e-label>ANYTEXT</note-e>
    def repl(match):
        nonlocal counter, metacounter
        replacement = f'<{tag_name}><{tag_name}-label data-fn="id{tag_name}{metacounter}{counter}">{counter}</{tag_name}-label><{tag_name}-content  data-fn="id{tag_name}{metacounter}{counter}">{match.group(1)}</{tag_name}-content></{tag_name}>'
        counter = chr(ord(counter) + 1)
        if counter == 'z': 
            counter = 'a'
            metacounter += 1
        elif counter == 'Z': 
            counter = 'A'
            metacounter +=1
        return replacement
    html_content = regex.sub(pattern, repl, html_content)
    return html_content

# adds in html_content to each tag_name-tag -label and -content tags and includes index-categories
def replace_tag_index(html_content, tag_name, data_cat):
    # Define a counter starting from 1
    counter = 1
    if tag_name == 'fac-simile': 
        label = '&#128366;'
        tag = 'fac-simile'
    elif tag_name == 'in-dex class="person"':
        label = 'P'
        tag = 'in-dex'
    elif tag_name == 'in-dex class="institution"':
        label = 'I'
        tag = 'in-dex'
    elif tag_name == 'in-dex class="sache"':
        label = 'C'
        tag = 'in-dex'
    elif tag_name == 'in-dex class="location"':
        label = 'L'
        tag = 'in-dex'
    elif tag_name == 'in-dex class="doc"':
        label = data_cat
        tag = 'in-dex'
        tag_name = 'in-dex class="doc" data-cat="' + data_cat + '"'
    elif tag_name == 'loc-ation':
        label = 'O'
        tag = 'loc-ation'
    else:
        return html_content 

    # Define a pattern to match <tag_name>ANYTEXT</tag_name>
    pattern = fr'<{tag_name}>(.*?)<\/{tag}>'
    # Replace occurrences of <note-e>ANYTEXT</note-e> with <note-e><note-e-label>n</note-e-label>ANYTEXT</note-e>
    def repl(match):
        nonlocal counter, label
        replacement = f'<{tag_name}><{tag}-label data-fn="id{tag}{label}{counter}">{label}</{tag}-label><{tag}-content  data-fn="id{tag}{label}{counter}">{match.group(1)}</{tag}-content></{tag}>'
        counter += 1
        return replacement
    html_content = regex.sub(pattern, repl, html_content)
    return html_content

# Transforms content in LaTeX, espacially bibliographical entries, into more convenient text
# TODO: I also have to use this function in the diaries! see function replace_tag_index
def normalize_bib(text):
    text = text.replace("\hbox{--}", "‒")
    text = text.replace("--", "‒")
    text = text.replace("''", '"')
    parts = text.split("!", 1)

    if len(parts) == 2:
        left, right = parts

        # führenden Text bis inklusive @ löschen
        left = regex.sub(r'^.*@', '', left).strip()
        right = regex.sub(r'^.*@', '', right).strip()

        text = f"{left}: {right}"

    else:
        # auch ohne ! führenden Text bis @ entfernen
        text = regex.sub(r'^.*@', '', text).strip()
    
     # \emph{...} -> <em>...</em>
    text = regex.sub(
        r'\\emph\{([^{}]*)\}',
        r'<em>\1</em>',
        text
    )

    return text.strip()

TRIGGER_FILES = {
    "PersonEntry": "D:\\RCD\\texmf\\tex\\latex\\valep\\db-persons.sty",
    "InstEntry": "D:\\RCD\\texmf\\tex\\latex\\valep\\db-institutions.sty",
    "SacheEntry": "D:\\RCD\\texmf\\tex\\latex\\valep\\db-concepts-aufbau.sty",
    "WorkEntry": "D:\\RCD\\texmf\\tex\\latex\\valep\\db-documents.sty",
    "CWorkEntry": "D:\\RCD\\texmf\\tex\\latex\\valep\\db-documents.sty",
}

# together with replace_triggers and TRIGGER_FILES it replaces all triggers with content from the respective db- Files
def find_replacement_in_file(file_path, cls, trigger):
    text = Path(file_path).read_text(encoding="utf-8")

    command = "\\" + cls + "{" + trigger + "}"
    pos = text.find(command)

    if pos == -1:
        return None

    rest = text[pos + len(command):]
    lines = rest.splitlines()

    # leere Zeilen überspringen
    lines = [line.strip() for line in lines if line.strip()]

    if len(lines) < 2:
        return None

    second_line = lines[1]

    if second_line.startswith("{") and second_line.endswith("}"):
        replacement = second_line[1:-1].strip()
        replacement = normalize_bib(replacement)

        return replacement

    return None


def replace_triggers(html_content):
    html_pattern = regex.compile(
        r'''
        <trig-ger
        \b[^>]*\bclass=["']([^"']+)["'][^>]*>
        (.*?)
        </trig-ger>
        ''',
        regex.IGNORECASE | regex.DOTALL | regex.VERBOSE
    )

    def replace_match(match):
        class_attr = match.group(1)
        content = match.group(2)

        trigger = content.strip()
        classes = class_attr.split()

        for cls in classes:
            if cls in TRIGGER_FILES:
                replacement = find_replacement_in_file(
                    TRIGGER_FILES[cls],
                    cls,
                    trigger
                )

                if replacement is not None:
                    # trig-ger Tag komplett ersetzen
                    return replacement

        return match.group(0)

    return html_pattern.sub(replace_match, html_content)


# adds to each tag_name tag a -label tag before it
def add_tag_label(html_content, tag_name, label):
    counter = 1
    def repl(match):
        nonlocal counter
        replacement = f'<{tag_name}-label data-fn="id{tag_name}{counter}">{label}</{tag_name}-label><{tag_name}  data-fn="id{tag_name}{counter}">'
        counter += 1
        return replacement
    html_content = regex.sub(fr'<{tag_name}>', repl, html_content)
    return html_content

# adds in html_content to each tag_name-tag -label and -content tags, numbering footnote symbols *, etc.
def replace_tag_symbols(html_content, tag_name):
    # counters are an array of symbols plus a metacounter that is incremented whenever the array is looped
    counter = ['*', '†', '‡', '§', '¶', '#', '♠', '♥', '♦', '♣']
    metacounter = 1
    i = 0
    # Define a pattern to match <tag_name>ANYTEXT</tag_name>
    pattern = fr'<{tag_name}>(.*?)<\/{tag_name}>'
    # Replace occurrences of <note-e>ANYTEXT</note-e> with <note-e><note-e-label>n</note-e-label>ANYTEXT</note-e>
    def repl(match):
        nonlocal counter, i, metacounter
        replacement = f'<{tag_name}><{tag_name}-label data-fn="id{tag_name}{metacounter}-{i}">{counter[i]}</{tag_name}-label><{tag_name}-content  data-fn="id{tag_name}{metacounter}-{i}">{counter[i]} {match.group(1)}</{tag_name}-content></{tag_name}>'
        i = i+1
        if i == len(counter):
            i = 0
            metacounter = metacounter + 1
        return replacement
    html_content = regex.sub(pattern, repl, html_content)
    return html_content

# adds labels to reading lists
def add_all_to_reading_lists(html_content):
    counter = 0
    reset = regex.search(r'<set-counter data-counter="leseliste" data-value="(\d+)"', html_content)
    if reset:
        counter = int(reset.group(1))
    def repl(match):
        nonlocal counter
        counter += 1
        replacement = f'<rl-label id="{match.group(1)}" data-tooltip="Internal ID = {match.group(1)}">{counter}</rl-label>'
        return replacement
    html_content = regex.sub(r'<rl-label id="(.*?)"></rl-label>', repl, html_content)

    return html_content

# adds in html_content to each time-tag of the class "diary-entry" the correct description of the date
def fill_time_tags(html_content):
    # Define a pattern to match <time class="diary-entry" data-type="TEXTA" datetime="TEXTB">ANYTEXT</time>
    pattern = fr'<time class="diary-entry" data-type="(.*?)" datetime="(.*?)" id="(.*?)">(.*?)<\/time>'
    def repl(match):
        dat = match.group(2).split('-')
        path = f'entries/{dat[0]}/entry-{match.group(2)}.html'
        if os.path.isfile(path):
            replacement = f'<a class="entryfile" href="{path}"><time class="diary-entry" data-type="{match.group(1)}" datetime="{match.group(2)}" data-tooltip="{nice_date(match.group(2))}" id="{match.group(3)}">{make_date(match.group(2),match.group(1))} {match.group(4)}</time></a>'
        else:
            replacement = f'<a class="entryfile" href><time class="diary-entry" data-type="{match.group(1)}" datetime="{match.group(2)}" data-tooltip="{nice_date(match.group(2))}" id="{match.group(3)}">{make_date(match.group(2),match.group(1))} {match.group(4)}</time>'
            print(f'WARNING: {path} does not seem to exist!')
        return replacement
    html_content = regex.sub(pattern, repl, html_content)

    # second step: add monthly labels in left margin
    # first for long and llong
    pattern= fr'<time class="diary-entry" data-type="(long|llong)" datetime="(\d*-\d*-\d*)"'
    def repll(match):
        month = make_month(match.group(2))
        replacement = f'<diary-month id="month-id:{match.group(2)}">{month}</diary-month><time class="diary-entry" data-type="{match.group(1)}" datetime="{match.group(2)}"'
        return replacement
    html_content = regex.sub(pattern, repll, html_content)
    # second for first day of month
    pattern= fr'<time class="diary-entry" data-type="normal" datetime="(\d*-\d*-1)"'
    def replll(match):
        month = make_month(match.group(1))
        replacement = f'<diary-month id="month-id:{match.group(1)}">{month}</diary-month><time class="diary-entry" data-type="normal" datetime="{match.group(1)}"'
        return replacement
    html_content = regex.sub(pattern, replll, html_content)

    return html_content

# merges mark- and text- tags of the type tag_name and puts the content in a tag_name-tag
def merge_mark_and_text(html_content, tag_name):
    # Define a pattern to match <tag_name-mark> SOMETHING <tag_name-text> 
    pattern = fr'<{tag_name}-mark><\/{tag_name}-mark>([\s\S]*?)<{tag_name}-text>(.*?)<\/{tag_name}-text>'
    i = 0
    def repl(match):
        nonlocal i
        replacement = f'<{tag_name}><{tag_name}-label data-fn="id{tag_name}-tab-{i}"> {match.group(2)}</{tag_name}>{match.group(1)}'
        i += 1
        return replacement
    
    while regex.search(pattern, html_content):
        html_content = regex.sub(pattern, repl, html_content)

    return html_content


def merge_bilingual(html_content, stack):

    pattern = regex.compile(
        r'<!--\s*hidden-begin\s*-->(.*?)<!--\s*hidden-end\s*-->',
        regex.DOTALL
    )

    match = pattern.search(html_content)

    if match:
        # Inhalt speichern
        html_trans = match.group(1)

        # Bereich aus html_content entfernen
        html_content = pattern.sub('', html_content, count=1)
    else:
        html_trans = ""
    
    pattern = regex.compile(
        r'<!--\s*bilingual-begin\s*-->(.*?)<!--\s*bilingual-end\s*-->',
        regex.DOTALL
    )

    if pattern.search(html_content):
        
        def process_block(match):
                
            content = match.group(1)

            orig_pattern = regex.compile(
                r'<!--\s*orig-begin\s+"([A-Za-z0-9_.\- ]+)"\s+"([A-Za-z0-9_.\- ]+)"\s*-->'
                r'(.*?)'
                r'<!--\s*orig-end\s+"\1"\s+"\2"\s*-->',
                regex.DOTALL
            )

            def split_paragraph_blocks(s):
                marker = r'<!--\s*paragraph-html\s*-->'

                if not regex.search(marker, s):
                    return [s]

                paragraph_pattern = regex.compile(
                    r'(<p\b[^>]*>\s*' + marker + r'.*?</p>)',
                    regex.DOTALL
                )

                parts = paragraph_pattern.split(s)

                blocks = []
                for part in parts:
                    if part.strip():
                        part = regex.sub(marker, '', part)
                        blocks.append(part)

                return blocks
            
            def replace_orig(match):
                x = match.group(1)
                y = match.group(2)
                a = match.group(3)

                trans_pattern = regex.compile(
                    r'<!--\s*trans-begin\s+"'
                    + regex.escape(y) +
                    r'"\s*-->'
                    r'(.*?)'
                    r'<!--\s*trans-end\s+"'
                    + regex.escape(y) +
                    r'"\s*-->',
                    regex.DOTALL
                )

                trans_match = trans_pattern.search(html_trans)

                if not trans_match:
                    return a

                b = trans_match.group(1)

                a_blocks = split_paragraph_blocks(a)
                b_blocks = split_paragraph_blocks(b)

                pairs = []

                for a_block, b_block in zip(a_blocks, b_blocks):
                    pairs.append(f'''<div class="paragraph-pair">
                <div class="original">
            {a_block}
                </div>
                <div class="translation">
            {b_block}
                </div>
            </div>''')

                return f'''<div class="parallel-text">
            {chr(10).join(pairs)}
            </div>'''

            content = orig_pattern.sub(replace_orig, content)
            
            return (
                '<!-- bilingual-begin -->'
                + content +
                '<!-- bilingual-end -->'
            )

        html_content = pattern.sub(process_block, html_content)

    else:
        # alternative Prozedur für einzelne Files, die keine bilingual Umgebung haben
        pass

    return html_content, stack


# produces the correct title and adds the table of content and other things
def make_title_toc(html_content, stack):
    file_name = stack.filename
    
    # here some general post processing things can be done 
    # <li > elements normalization
    def value_to_number(y: str) -> int:
        original = y

        # HTML-Tags raus
        y = regex.sub(r"<[^>]+>", "", y)

        # Ersten sinnvollen Marker suchen: Zahl oder Buchstabe
        m = regex.search(r"\p{L}|\d+", y)

        if not m:
            raise ValueError(f"Kein verwertbarer li value: {original!r}")

        token = m.group(0).lower()

        if token.isdigit():
            return int(token)

        # Buchstabe: a=1, b=2, ...
        if len(token) == 1:
            return ord(token) - ord("a") + 1

        raise ValueError(f"Ungültiger value: original={original!r}, token={token!r}")

    def replace_li(match: regex.Match) -> str:
        value = match.group("value")

        # Kein value vorhanden
        if value is None:
            return '<li class="nonumber">'

        z = value_to_number(value)

        return f'<li class="numbered" value="{z}">'

    pattern = r'''
    <li
    (?:
        \s+value\s*=\s*"(?P<value>[^"]+)"
    )?
    \s*>
    '''

    html_content = regex.sub(
        pattern,
        replace_li,
        html_content,
        flags=regex.VERBOSE
    )
    
    
    if stack.carnapedition:
        # Define pattern to find primary headline 
        # Parse the HTML content
        doc_type = 'letter'
        
        # April 2026: I need to write a signature in all documents of the Collected Works and the Critical Edition that allows us to identify the exact content
        # On this basis I can then create the document structure here 
        
        pattern = regex.compile(
            r'<doc-id([^>]*)>(.*?)</doc-id>',
            regex.DOTALL
        )
        match = pattern.search(html_content)

        def replace_doc_id(match):
            attrs = match.group(1)
            title = match.group(2).strip()

            # Attribute extrahieren
            creath_no = regex.search(r'creath-no="(.*?)"', attrs)
            ed_iton   = regex.search(r'ed-iton="(.*?)"', attrs)
            sec_tion  = regex.search(r'sec-tion="(.*?)"', attrs)

            creath_no_val = creath_no.group(1) if creath_no else ""
            creathno = f' ({creath_no.group(1)})' if creath_no else ""
            ed_iton_val   = ed_iton.group(1) if ed_iton else ""
            sec_tion_val  = sec_tion.group(1) if sec_tion else ""

            section = ''

            if ed_iton_val == "CPub" and sec_tion_val: section = f', {sec_tion_val}'

            # Neues h1-Tag bauen
            new_attrs = ""
            new_attrs += f' class="doc-id"'
            if creath_no_val:
                new_attrs += f' creath-no="{creath_no_val}"'
            if ed_iton_val:
                new_attrs += f' ed-iton="{ed_iton_val}"'
            if sec_tion_val:
                new_attrs += f' sec-tion="{sec_tion_val}"'

            return f"<h1{new_attrs}>{title}</h1>"

        if match:
            html_content = pattern.sub(replace_doc_id, html_content)
            title = match.group(2).strip()
            html_content = regex.sub('<div class="menu-text" id="top-menu-text">(.*?)</div>',f'<div class="menu-text" id="top-menu-text">{title}</div>',html_content,1)

        elif len(file_name) == 2 and file_name.isdigit():
            doc_type = 'diarychapter'
            n = int(file_name)
            if 0 < int(n) < 22:
                html_content = regex.sub('<a class="chapterup" href=".*?">','<a class="chapterup" href="https://valep.vc.univie.ac.at/files/Tagebuecher/Tagebuecher_1908_bis_1919.html">',html_content,1)
                html_content = html_content.replace('<div class="jumpup" data-tooltip="go up" style="visibility:hidden;">', '<div class="jumpup" data-tooltip="go up" style="visibility:visible;">')
                html_content = regex.sub('<div class="menu-text" id="top-menu-text">.*?</div>', '<div class="menu-text" id="top-menu-text"><i class="spaced">Rudolf Carnap.</i> Tagebücher und Leselisten. 1908–1919</div>', html_content)
            elif 21 < int(n) < 40:
                html_content = regex.sub('<a class="chapterup" href=".*?">','<a class="chapterup" href="https://valep.vc.univie.ac.at/files/Tagebuecher/Tagebuecher_1920_bis_1935.html">',html_content,1)
                html_content = html_content.replace('<div class="jumpup" data-tooltip="go up" style="visibility:hidden;">', '<div class="jumpup" data-tooltip="go up" style="visibility:visible;">')
                html_content = regex.sub('<div class="menu-text" id="top-menu-text">.*?</div>', '<div class="menu-text" id="top-menu-text"><i class="spaced">Rudolf Carnap.</i> Tagebücher und Leselisten. 1920–1935</div>', html_content)
            elif 39 < int(n) < 57:
                html_content = regex.sub('<a class="chapterup" href=".*?">','<a class="chapterup" href="https://valep.vc.univie.ac.at/files/Tagebuecher/Tagebuecher_1936_bis_1952.html">',html_content,1)
                html_content = html_content.replace('<div class="jumpup" data-tooltip="go up" style="visibility:hidden;">', '<div class="jumpup" data-tooltip="go up" style="visibility:visible;">')
                html_content = regex.sub('<div class="menu-text" id="top-menu-text">.*?</div>', '<div class="menu-text" id="top-menu-text"><i class="spaced">Rudolf Carnap.</i> Tagebücher und Leselisten. 1936–1952</div>', html_content)
            elif 56 < int(n) < 66:
                html_content = regex.sub('<a class="chapterup" href=".*?">','<a class="chapterup" href="https://valep.vc.univie.ac.at/files/Tagebuecher/Tagebuecher_1952_bis_1962.html">',html_content,1)
                html_content = html_content.replace('<div class="jumpup" data-tooltip="go up" style="visibility:hidden;">', '<div class="jumpup" data-tooltip="go up" style="visibility:visible;">')
                html_content = regex.sub('<div class="menu-text" id="top-menu-text">.*?</div>', '<div class="menu-text" id="top-menu-text"><i class="spaced">Rudolf Carnap.</i> Tagebücher und Leselisten. 1952–1962</div>', html_content)
            elif 65 < int(n) < 75:
                html_content = regex.sub('<a class="chapterup" href=".*?">','<a class="chapterup" href="https://valep.vc.univie.ac.at/files/Tagebuecher/Tagebuecher_1962_bis_1970.html">',html_content,1)
                html_content = html_content.replace('<div class="jumpup" data-tooltip="go up" style="visibility:hidden;">', '<div class="jumpup" data-tooltip="go up" style="visibility:visible;">')
                html_content = regex.sub('<div class="menu-text" id="top-menu-text">.*?</div>', '<div class="menu-text" id="top-menu-text"><i class="spaced">Rudolf Carnap.</i> Tagebücher und Leselisten. 1962–1970</div>', html_content)

        elif file_name[0:11] == 'Tagebuecher':
            doc_type = 'diaryvolume'
            von = int(file_name[12:16])
            bis = int(file_name[21:25])
            title = f'<i class="spaced">RUDOLF CARNAP</i>. Tagebücher und Leselisten. {von}–{bis}'
            # add title to the tool bar
            html_content = regex.sub('<div class="menu-text" id="top-menu-text">(.*?)</div>',f'<div class="menu-text" id="top-menu-text">{title}</div>',html_content,1)
            # hide the go up arrow
            html_content = regex.sub('<div class="jumpup" data-tooltip="go up">','<div class="jumpup" data-tooltip="go up" style="visibility: hidden;">',html_content,1)
            # add title to the top of the document if the document does not already start with a volume title
            title = f'<i class="spaced">RUDOLF CARNAP</i><br />Tagebücher und Leselisten<br />{von}–{bis}'
            first_title = regex.search('<h1 id="(.*?)" class="(.*?)">', html_content)
            if first_title == None or (first_title and not first_title.group(2) == "volume"):
                html_content = regex.sub('<div class="allcont">', f'<div class="allcont">\n\n<h1 class="volume">{title}</h1>', html_content)
        else:
            # letters: deal with this in a proper way
            html_content = regex.sub('<div class="jumpup" data-tooltip="go up">','<div class="jumpup" data-tooltip="go up" style="visibility: hidden;">',html_content,1)

        matches = regex.findall(r'<h([1234]{1}) id="(.*?)" class="(.*?)".*?>(.*?)</h\1>', html_content)
        toc = ""
        if len(matches) > 1:
            # if there is more than one heading produce a toc with the headings h1 to h3
            toc = "<p>"
            for match in matches:
                if not match[2] == "volume":
                    if match[0] == '1':
                        indent = ''
                    elif match[0] == '2':
                        indent = '&#8193;'
                    elif match[0] == '3':
                        indent = '&#8193;&#8193;'
                    else:
                        indent = '&#8193;&#8193;&#8193;'
                    cleaned = regex.sub(
                        r'<(?:new-p|note-a|fac-simile)>.*?</(?:new-p|note-a|fac-simile)>',
                        '',
                        match[3],
                        flags=regex.DOTALL
                    )

                    toc += f'<a class="toc-link" href="#{match[1]}">{indent}{cleaned}</a><br>\n'
            toc += "</p>"
            safe_toc = toc.replace("\\", "\\\\")   # there are label commands or some commands starting with \l in the \paragraph headers, these are misinterpreted as escape-sequences
            html_content = regex.sub('<div class="toc-dropdown">',f'<div class="toc-dropdown">\n{safe_toc}',html_content)
            # if there are several chapters add links to each headline that allow to open them individually
            def repl(match):
                chpt = match.group(2)
                if len(chpt) == 1:
                    chpt = '0' + chpt
                replacement = f'<a class="chapterfile" href="{chpt}.html"><h1 id="{match.group(1)}" class="diaries"><diary-no>{match.group(2)}</diary-no>{match.group(3)}</h1></a>'
                return replacement
            html_content = regex.sub(r'<h1 id="(.*?)" class="diaries"><diary-no>(.*?)</diary-no>(.*?)</h1>',repl,html_content)


        elif doc_type == 'diarychapter':
            # if there is only one heading of class "diaries" produce a toc with data information
            matches = regex.findall(r'<diary-month id="(.*?)">(.*?)</diary-month>', html_content)
            toc = "<p>"
            for match in matches:
                toc += f'<a class="toc-link" href="#{match[0]}">{match[1]}</a><br>\n'
            toc += "</p>"
            html_content = regex.sub('<div class="toc-dropdown">',f'<div class="toc-dropdown">\n{toc}',html_content)
        else:
            # otherwise produce no toc at all
            html_content = regex.sub('<div class="table-of-content">','<div class="table-of-content" style="visibility:hidden">',html_content)
    else: 
        matches = regex.findall(r'<h([123]{1}) id="(.*?)"[^>]*>(.*?)</h\1>', html_content)
        toc = ""
        # if there is more than one heading produce a toc with the headings h1 to h3
        toc = "<p>"
        for match in matches:
            if match[0] == '1':
                indent = ''
            elif match[0] == '2':
                indent = '&#8193;'
            else:
                indent = '&#8193;&#8193;'
            toc += f'<a class="toc-link" href="#{match[1]}">{indent}{match[2]}</a><br>\n'
        toc += "</p>"
        html_content = html_content.replace('<div class="toc-dropdown">',f'<div class="toc-dropdown">\n{toc}')
        

        if not stack.madetitle:
            match = regex.search(r'<h1.*?>(.*?)</h1>', html_content)
            if match: stack.madetitle = match.group(1)


        titl = stack.madetitle.replace('\\','\\\\')        
        titl = titl.replace('<br />', ' ')
        html_content = regex.sub(r'<div class="menu-text" id="top-menu-text">(.*?)</div>', 
                              rf'<div class="menu-text" id="top-menu-text">{titl}</div>', html_content)
        
        
        title = f'<h1 class="volume editor">{titl}</h1>'
        if not regex.search(r'<h1.*?class="volume"',html_content):
            html_content = regex.sub('<div class="allcont">', f'<div class="allcont">\n\n{title}', html_content)



    return html_content, stack

# matches an uglydate with date ranges of diary chapters, returns 0 if there is no match
def match_date_with_chapter(uglydate):
    chapter = '00'
    chapters = ['01']
    i=1
    while i < 74:
        i += 1
        if i < 10:
            chapters.append(f'0{i}')
        else:
            chapters.append(f'{i}')
    for chpt in chapters:
        try:
            with open(f'{chpt}.html', 'r', encoding='utf-8', newline='') as file:
                filecontent = file.read()
            if filecontent.find(f'id="entry-{uglydate}"') >= 0:
                chapter = chpt
        except:
            print(f'ERROR while searching for diary entries: File {chpt}.html could not be searched!')

    return chapter

# returns the diary chapter that contains the diary entry for a date (either current or none or chapter)
def get_diary_chapter(uglydate,html_content):
    if html_content.find(f'id="entry-{uglydate}"') >= 0:
        return "current"
    else:
        return match_date_with_chapter(uglydate)

# resolves references to diary entries that use the LaTeX command \diaryref
def resolve_diary_references(html_content):
    def repl(match):
        date = parse_date(match.group(1))
        nicedate = nice_date(date)
        diarychapter = get_diary_chapter(date,html_content)
        if diarychapter == 'current':
            replacement = f'<a class="diaryref" id="{match.group(1)}" href="#entry-{date}" data-tooltip="Eintrag: {nicedate}">R</a>'
        elif not diarychapter == '00':
            replacement = f'<a class="diaryref" id="{match.group(1)}" href="{diarychapter}.html#entry-{date}" data-tooltip="Eintrag: Kapitel {diarychapter}, {nicedate}">R</a>'
        else:
            replacement = f'<a class="diaryref" id="{match.group(1)}" style="display:none;"></a>'
        return replacement
    html_content = regex.sub('<a class="diaryref" id="(.*?)"></a>', repl, html_content)

    return html_content