"""compare commits of logs in different branches

selecting the time range is based on file 'sync_branches'
which should be in the branch where logdif.py is running
"""

import sys
from readchar import readchar
from subprocess import check_output

branches = sys.argv[1:3]

commits = {}
log_no = {}
cursor = {}
short_set = set()

if len(sys.argv) < 3:
    print('Usage: python3 logdif.py <branch1> <branch2> [<YYYY-mm-dd>]')
    sys.exit(0)

if len(sys.argv) > 3:
    since = sys.argv[3]
else:
    since_info = []

    with open("sync_branches") as f:
        # a file containing
        #  YYYY-mm-dd <branch1> <branch2>
        # for each date the branches are synced
        for line in f:
            if line.strip():
                info = line.split()
                if set(branches) & set(info[1:3]) == set(branches):
                    since_info.append(info[0])
    since = sorted(since_info)[-1] if since_info else None


gitlog = ['git', 'log', '--oneline']
if since:
    gitlog.append(f'--since-as-filter={since}')
else:
    print(f'no info for {branches} found in file sync_branches')

for br in branches:
    cursor[br] = 0
    # collect hashes of commis newer than since
    short_output = check_output(gitlog + [br])
    for line in short_output.decode('utf-8').split('\n'):
        if line:
            short_set.add(line.split(' ', 1)[0])
    output = check_output(gitlog[:3] + [br])
    log_no[br] = byno = []
    no = 0
    for line in output.decode('utf-8').split('\n'):
        if line:
            commit, title = line.split(' ', 1)
            byno.append([commit, title])
            no += 1

# find matches
for br, byno in log_no.items():
    for no, line in enumerate(byno):
        commits.setdefault(line[1], {}).setdefault(br, []).append((no, line))

ordered = {}
for title, info in commits.items():
    # sort the info dict by value
    ordered[title] = {b: v for v, b in sorted((v, b) for b, v in info.items())}

commits = ordered

cnt = [0]


def print_commit(line):
    if not line[1]:
        return  # title cleared: this line is already printed
    # print and mark line as already printed
    info = commits[line[1]]
    output = []
    title = line[1]
    visible = False
    for br in log_no:
        infolist = info.get(br)
        if infolist:
            no, iline = infolist.pop(0)
            if not infolist:
                info.pop(br)
            if iline[0] in short_set:
                visible = True
            output.append(f'{no:3}:{iline[0]}')
            iline[1] = ''  # clear title
        else:
            output.append(' ' * 12)
    if visible:
        print(' '.join(output), title)
        cnt[0] += 1
        if cnt[0] % 50 == 0:
            print(f' {br0:12s} {br1:12s}--- press any letter to continue, return to stop ---')
            if readchar() in 'q\n':
                raise StopIteration()


(br0, log0), (br1, log1) = list(log_no.items())
no1 = 0
try:
  for no0, line0 in enumerate(log0):
    if line0[1]:  # line not yet printed
        infodict = commits[line0[1]]
        if len(infodict) > 1:  # found a match
            info0 = infodict[br1]
            # loop over commits in br1 until matched no
            no1end = info0[0][0]
            if no1end > no0:
                for n in range(no0, no1end):
                    line1 = log1[n]
                    print_commit(line1)
                no1 = no1end
        print_commit(line0)
except StopIteration:
   pass
