#################################################
### THIS FILE WAS AUTOGENERATED! DO NOT EDIT! ###
#################################################
# file to edit: ./nb/common.ipynb
import os
IN_TRAVIS=(os.getenv('TRAVIS', False) == 'true')
CLI_TEST=(os.getenv('CLI_TEST', False) == 'true')

def overwrite_by_env(current_value, env_name):
    if (os.getenv(env_name, False) == 'true'):
        print(f"overwriting True by env {env_name}:true")
        return True
    if (os.getenv(env_name, False) == 'false'):
        print(f"overwriting True by env {env_name}:false")
        return False
    return current_value

exp_dir_name = 'xs_lib'
working_dir_tag = 'nb'

#https://stackoverflow.com/questions/15411967/how-can-i-check-if-code-is-executed-in-the-ipython-notebook
def isnotebook():
    try:
        shell = get_ipython().__class__.__name__
        if shell == 'ZMQInteractiveShell':
            return True   # Jupyter notebook or qtconsole
        elif shell == 'TerminalInteractiveShell':
            return False  # Terminal running IPython
        else:
            return False  # Other type (?)
    except NameError:
        return False      # Probably standard Python interpreter
IN_JUPYTER = isnotebook()

IN_TRAVIS=overwrite_by_env(IN_TRAVIS, "IN_TRAVIS")
IN_JUPYTER =overwrite_by_env(IN_JUPYTER, "IN_JUPYTER")

class _simple_tqdm:
    """
    for travis
    """
    def __init__(self, g):
        self.g = g
        try:
            l = len(g)
        except TypeError:
            l = '?'
        self.l = l

    def __iter__(self):
        for i,x in enumerate(self.g):
            print(f"({i}/{self.l})", end='')
            yield x

    def __len__(self):
        return self.l
try:
    if IN_JUPYTER:
        from tqdm.notebook import tqdm as notebook_tqdm
        tqdm = notebook_tqdm
    else :
        from tqdm import _tqdm
        tqdm = _tqdm.tqdm
except:
    tqdm = _simple_tqdm


def ex_sh_cmd(code):
    ip = get_ipython()
    # this depends on the environment where jupyter launchs
    ip.run_cell(code)

# todo
# 支持多级结构import, output，但可能不会用到
import json,re
from pathlib import Path
import io
import os
import os.path

class NBExporter:
    """
    single notebook exporter
    """
    def __init__(self, tag='export', prefix=''):
        self.tag = tag
        self.prefix = prefix

    def is_export(self, cell, ):
        tag = self.tag
        if cell['cell_type'] != 'code': return False
        src = cell['source']
        if len(src) == 0 or len(src[0]) < 7: return False
        #import pdb; pdb.set_trace()
        reg = f'^\s*#\s*{tag}\s*$'
        reg = re.compile(reg, re.IGNORECASE,)
        return re.match(reg, src[0], ) is not None


    def __call__(self, fname, to='../exp'):
        "Finds cells starting with `#export` and puts them into a new module"
        fname = Path(fname)
        to = Path(to)
        if(os.path.isdir(to)):
            # overwrite the defulat filename
            fname_out = f'{fname.stem.split(".")[0]}.py'
            fname_out = f'{self.prefix}{fname_out}'
            output_path = to/fname_out

        elif(str(to.absolute())[-3:]==".py"):
            output_path = to
        else:
            print("ERR a dir or a file ends with .py is needed")
            exit(1)

        if(os.path.exists(output_path)):print(f"overwriting {output_path}")

        main_dic = json.load(open(fname,'r',encoding="utf-8"))
        code_cells = [c for c in main_dic['cells'] if self.is_export(c)]
        module = f'''#################################################
### THIS FILE WAS AUTOGENERATED! DO NOT EDIT! ###
#################################################
# file to edit: ./nb/{fname.name}
'''

#         import pdb; pdb.set_trace()
        for cell in code_cells: module += ''.join(cell['source'][1:]) + '\n\n'
        # remove trailing spaces
        module = re.sub(r' +$', '', module, flags=re.MULTILINE)


        with io.open(output_path, "w", encoding="utf-8") as f:
            f.write(module[:-2])
        print(f"Converted {fname} to {output_path}")



class Export_notebook:
    """
    export notebook in a project
    """
    def __init__(self, dst, working_dir_tag = 'nb'):
        self.export_model = NBExporter()
        self.export_test = NBExporter('(test_)?export', prefix='test_')
        self.dst = dst
        self.working_dir_tag = working_dir_tag

    def sub_path(self, dst):
        rv = lambda s:s[::-1] # revserse string
        current = os.getcwd()
        tag = self.working_dir_tag
        assert tag in current, f"{tag, current}"

        current = rv(current)
        dst = rv(dst)
        tag = rv(tag)
        current = current.replace(tag, dst, 1)
        current = rv(current)

        return current

    def __call__(self, name,):
        assert IN_JUPYTER

        save_notebook()
        NOTEBOOK_EXTEND_NAME='.ipynb'
        if NOTEBOOK_EXTEND_NAME not in name:
            name += NOTEBOOK_EXTEND_NAME
        time.sleep(1)

        test_path = self.sub_path('tests')
        exp_path = self.sub_path(self.dst)

        # support import complie
        self.export_model(name, to=exp_path)
        self.export_test(name, to=test_path)

        save_notebook() # for exitting




# use those only in jupyter
import time

def save_notebook():
    ex_js_cmd('IPython.notebook.save_checkpoint();')

def restart_kernel():
    ex_js_cmd('IPython.notebook.kernel.restart();')

def kill_kernel():
    ex_js_cmd('IPython.notebook.kernel.kill();')

def ex_js_cmd(cmd):
    from IPython.display import display, Javascript
    display(Javascript(cmd))

save_and_export_notebook = Export_notebook(exp_dir_name, working_dir_tag = working_dir_tag )


def cli_main(fname, dst='./'):
    """
    cli interface to convert ipynb to py

    Examples:
        nb2py ./nb/common.ipynb ./ # export to ./common.py and ./test_common.py
        nb2py ./nb/common.ipynb ./common.export.test.py # export #export tag only
    Argument:
        fname: required. ipynb file to convert.
        dst: default to `./`. where to put the exported py file.  export both #test_export and #export cell if a dir is provided. export #export only if a file is provided.
    """
    assert fname[-6:]==".ipynb"

    export_model = NBExporter()
    export_test = NBExporter('(test_)?export', prefix='test_')
    if(os.path.isdir(dst)):
        export_model(fname, dst)
        export_test(fname, dst)
    else:
        export_model(fname, dst)

def fire_main():
    import fire
    fire.Fire(cli_main)


if __name__ == '__main__':
    if CLI_TEST:
        fire_main()
    elif IN_JUPYTER or IN_TRAVIS:
        pass
    else:
        fire_main()