# AUTOGENERATED! DO NOT EDIT! File to edit: nbs/05_merge.ipynb (unless otherwise specified).

__all__ = ['extract_cells', 'get_md_cell', 'conflicts', 'same_inputs', 'analyze_cell', 'fix_conflicts']

# Cell
from .imports import *

# Cell
def extract_cells(raw_txt):
    "Manually extract cells in potential broken json `raw_txt`"
    lines = raw_txt.split('\n')
    cells = []
    i = 0
    while not lines[i].startswith(' "cells"'): i+=1
    i += 1
    start = '\n'.join(lines[:i])
    while lines[i] != ' ],':
        while lines[i] != '  {': i+=1
        j = i
        while not lines[j].startswith('  }'): j+=1
        c = '\n'.join(lines[i:j+1])
        if not c.endswith(','): c = c + ','
        cells.append(c)
        i = j+1
    end = '\n'.join(lines[i:])
    return start,cells,end

# Cell
def get_md_cell(txt):
    "A markdown cell with `txt`"
    return '''  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "''' + txt + '''"
   ]
  },'''

# Cell
conflicts = '<<<<<<< ======= >>>>>>>'.split()

# Cell
def _split_cell(cell, cf, names):
    "Split `cell` between `conflicts` given state in `cf`, save `names` of branches if seen"
    res1,res2 = [],[]
    for line in cell.split('\n'):
        if line.startswith(conflicts[cf]):
            if names[cf//2] is None: names[cf//2] = line[8:]
            cf = (cf+1)%3
            continue
        if cf<2:    res1.append(line)
        if cf%2==0: res2.append(line)
    return '\n'.join(res1),'\n'.join(res2),cf,names

# Cell
_re_conflict = re.compile(r'^<<<<<<<', re.MULTILINE)

# Cell
def same_inputs(t1, t2):
    "Test if the cells described in `t1` and `t2` have the same inputs"
    if len(t1)==0 or len(t2)==0: return False
    try:
        c1,c2 = json.loads(t1[:-1]),json.loads(t2[:-1])
        return c1['source']==c2['source']
    except Exception as e: return False

# Cell
def analyze_cell(cell, cf, names, prev=None, added=False, fast=True, trust_us=True):
    "Analyze and solve conflicts in `cell`"
    if cf==0 and _re_conflict.search(cell) is None: return cell,cf,names,prev,added
    old_cf = cf
    v1,v2,cf,names = _split_cell(cell, cf, names)
    if fast and same_inputs(v1,v2):
        if old_cf==0 and cf==0: return (v2 if trust_us else v1),cf,names,prev,added
        v1,v2 = (v2,v2) if trust_us else (v1,v1)
    res = []
    if old_cf == 0:
        added=True
        res.append(get_md_cell(f'`{conflicts[0]} {names[0]}`'))
    res.append(v1)
    if cf ==0:
        res.append(get_md_cell(f'`{conflicts[1]}`'))
        if prev is not None: res += prev
        res.append(v2)
        res.append(get_md_cell(f'`{conflicts[2]} {names[1]}`'))
        prev = None
    else: prev = [v2] if prev is None else prev + [v2]
    return '\n'.join([r for r in res if len(r) > 0]),cf,names,prev,added

# Cell
def fix_conflicts(fname, fast=True, trust_us=True):
    "Fix broken notebook in `fname`"
    fname=Path(fname)
    shutil.copy(fname, fname.with_suffix('.ipynb.bak'))
    with open(fname, 'r') as f: raw_text = f.read()
    start,cells,end = extract_cells(raw_text)
    res = [start]
    cf,names,prev,added = 0,[None,None],None,False
    for cell in cells:
        c,cf,names,prev,added = analyze_cell(cell, cf, names, prev, added, fast=fast, trust_us=trust_us)
        res.append(c)
    if res[-1].endswith(','): res[-1] = res[-1][:-1]
    with open(f'{fname}', 'w') as f: f.write('\n'.join([r for r in res+[end] if len(r) > 0]))
    if fast and not added: print("Succesfully merged conflicts!")
    else: print("One or more conflict remains in the notebook, please inspect manually.")