# AUTOGENERATED! DO NOT EDIT! File to edit: nbs/00-documentation.ipynb (unless otherwise specified).

__all__ = ['convert_file_to_json', 'encode_file_as_utf8', 'convert_nb_to_md', 'MyHTMLParser', 'convert_df_to_md',
           'remove_empty_index_col', 'extract_div_to_md_table', 'extract_div_to_md_tables', 'clean_md_file_tables',
           'get_substring_idxs', 'clean_progress_bars', 'correct_png_name', 'specify_nb_in_img_fp',
           'get_nb_naive_png_names', 'get_filename_correction_map', 'clean_md_text_img_fps', 'clean_md_files_img_fps',
           'convert_and_clean_nb_to_md']

# Cell
import json
import numpy as np
import pandas as pd

import junix
from html.parser import HTMLParser
from nbdev.export2html import convert_md

import os
import re
import codecs
from tqdm import tqdm
from warnings import warn

# Cell
def convert_file_to_json(filepath):
    with open(filepath, 'r', encoding='utf8') as f:
        contents = f.read()
        f.close()

    return json.loads(contents)

junix.exporter.convert_file_to_json = convert_file_to_json

def encode_file_as_utf8(fp):
    with codecs.open(fp, 'r') as file:
        contents = file.read(1048576)
        file.close()

        if not contents:
            pass
        else:
            with codecs.open(fp, 'w', 'utf-8') as file:
                file.write(contents)

def convert_nb_to_md(nb_file, nbs_dir, docs_nb_img_dir, docs_dir):
    if os.path.exists(docs_nb_img_dir) is False:
        os.makedirs(docs_nb_img_dir)

    nb_fp = f'{nbs_dir}/{nb_file}'
    junix.export_images(nb_fp, docs_nb_img_dir)
    convert_md(nb_fp, docs_dir, img_path=f'{docs_nb_img_dir}/', jekyll=False)

    md_fp =  docs_dir + '/'+ nb_file.replace('.ipynb', '') + '.md'
    encode_file_as_utf8(md_fp)

# Cell
class MyHTMLParser(HTMLParser):
    def __init__(self):
        super().__init__()
        self.tags = []

    def handle_starttag(self, tag, attrs):
        self.tags.append(self.get_starttag_text())

    def handle_endtag(self, tag):
        self.tags.append(f"</{tag}>")

get_substring_idxs = lambda string, substring: [num for num in range(len(string)-len(substring)+1) if string[num:num+len(substring)]==substring]

def convert_df_to_md(df):
    idx_col = df.columns[0]
    df = df.set_index(idx_col)

    if not isinstance(df.index.name, str):
        df.index.name = df.index.name[-1]

    df.columns = [col[0] if not isinstance(col, str) else col for col in df.columns]

    table_md = df.to_markdown()

    return table_md

def remove_empty_index_col(df):
    if 'Unnamed: 0' not in df.columns:
        return df

    if (df['Unnamed: 0']==pd.Series(range(df.shape[0]), name='Unnamed: 0')).mean()==1:
        df = df.drop(columns=['Unnamed: 0'])

    return df

def extract_div_to_md_table(start_idx, end_idx, table_and_div_tags, file_txt):
    n_start_divs_before = table_and_div_tags[:start_idx].count('<div>')
    n_end_divs_before = table_and_div_tags[:end_idx].count('</div>')

    div_start_idx = get_substring_idxs(file_txt, '<div>')[n_start_divs_before-1]
    div_end_idx = get_substring_idxs(file_txt, '</div>')[n_end_divs_before]

    div_txt = file_txt[div_start_idx:div_end_idx]
    potential_dfs = pd.read_html(div_txt)

    assert len(potential_dfs) == 1, 'Multiple tables were found when there should be only one'
    df = potential_dfs[0]
    df = remove_empty_index_col(df)
    md_table = convert_df_to_md(df)

    return div_txt, md_table

def extract_div_to_md_tables(md_fp):
    with open(md_fp, 'r') as f:
        file_txt = f.read()

    parser = MyHTMLParser()
    parser.feed(file_txt)

    table_and_div_tags = [tag for tag in parser.tags if tag in ['<div>', '</div>', '<table border="1" class="dataframe">', '</table>']]

    table_start_tag_idxs = [i for i, tag in enumerate(table_and_div_tags) if tag=='<table border="1" class="dataframe">']
    table_end_tag_idxs = [table_start_tag_idx+table_and_div_tags[table_start_tag_idx:].index('</table>') for table_start_tag_idx in table_start_tag_idxs]

    div_to_md_tables = []

    for start_idx, end_idx in zip(table_start_tag_idxs, table_end_tag_idxs):
        div_txt, md_table = extract_div_to_md_table(start_idx, end_idx, table_and_div_tags, file_txt)
        div_to_md_tables += [(div_txt, md_table)]

    return div_to_md_tables

def clean_md_file_tables(md_fp):
    div_to_md_tables = extract_div_to_md_tables(md_fp)

    with open(md_fp, 'r') as f:
        md_file_text = f.read()

    for div_txt, md_txt in div_to_md_tables:
        md_file_text = md_file_text.replace(div_txt, md_txt)

    with open(md_fp, 'w') as f:
        f.write(md_file_text)

    return

# Cell
def clean_progress_bars(md_fp, dodgy_char='Ã¢â€“Ë†'):
    with open(md_fp, 'r') as f:
        md_file_text = f.read()

    md_file_text = md_file_text.replace(f'|{dodgy_char}', '').replace(f'{dodgy_char}|', '').replace(dodgy_char, '')

    with open(md_fp, 'w') as f:
        f.write(md_file_text)

    return

# Cell
def correct_png_name(incorrect_png_name, md_fp):
    cell, output = incorrect_png_name.split('_')[1:]
    filename = md_fp.split('/')[-1][:-3]

    corrected_png_name = f"{filename}_cell_{int(cell)+1}_output_{output}"

    return corrected_png_name

get_nb_naive_png_names = lambda img_dir: [f[:-4] for f in os.listdir(img_dir) if f[:6]=='output']

def specify_nb_in_img_fp(md_fp, img_dir='img/nbs'):
    nb_naive_png_names = get_nb_naive_png_names(img_dir)
    nb_specific_png_names = [correct_png_name(nb_naive_png_name, md_fp) for nb_naive_png_name in nb_naive_png_names]

    for nb_naive_png_name, nb_specific_png_name in zip(nb_naive_png_names, nb_specific_png_names):
        old_img_fp = f'{img_dir}/{nb_naive_png_name}.png'
        new_img_fp = f'{img_dir}/{nb_specific_png_name}.png'

        os.remove(new_img_fp) if os.path.exists(new_img_fp) else None
        os.rename(old_img_fp, new_img_fp)

# Cell
def get_filename_correction_map(md_file_text, md_fp):
    png_idxs = [png_str.start() for png_str in re.finditer('.png\)', md_file_text)]
    png_names = [md_file_text[:png_idx].split('/')[-1] for png_idx in png_idxs]

    filename_correction_map = {
        f'{png_name}.png': f'{correct_png_name(png_name, md_fp)}.png'
        for png_name
        in png_names
        if png_name[:6] == 'output'
    }

    return filename_correction_map

def clean_md_text_img_fps(md_file_text, md_fp):
    md_file_text = md_file_text.replace('../docs/img/nbs', 'img/nbs')

    filename_correction_map = get_filename_correction_map(md_file_text, md_fp)

    for incorrect_name, correct_name in filename_correction_map.items():
        md_file_text = md_file_text.replace(incorrect_name, correct_name)

    return md_file_text

def clean_md_files_img_fps(md_fp):
    with open(md_fp, 'r') as f:
        md_file_text = f.read()

    md_file_text = clean_md_text_img_fps(md_file_text, md_fp)

    with open(md_fp, 'w') as f:
        f.write(md_file_text)

    return

# Cell
def convert_and_clean_nb_to_md(nbs_dir, docs_nb_img_dir, docs_dir):
    nb_files = [f for f in os.listdir(nbs_dir) if f[-6:]=='.ipynb' and f!='00-documentation.ipynb']

    for nb_file in tqdm(nb_files):
        convert_nb_to_md(nb_file, nbs_dir, docs_nb_img_dir, docs_dir)

        md_fp = docs_dir + '/' + nb_file.replace('ipynb', 'md')

        clean_md_file_tables(md_fp)
        clean_progress_bars(md_fp)
        specify_nb_in_img_fp(md_fp, img_dir=docs_nb_img_dir)
        clean_md_files_img_fps(md_fp)