# This file is part of the open-lmake distribution (git@github.com:cesar-douady/open-lmake.git)
# Copyright (c) 2023-2026 Doliam
# This program is free software: you can redistribute/modify under the terms of the GPL-v3 (https://www.gnu.org/licenses/gpl-3.0.html).
# This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

if __name__!='__main__' :

    import os
    import os.path as osp
    import re
    import sys

    import lmake
    from lmake.rules import PyRule

    from step import step

    lmake.manifest = (
        'Lmakefile.py'
    ,   'refs'
    ,   'step.py'
    )

    class Base(PyRule) :
        stems = {
            'File' : '.+'
        ,   'Any'  : '.+'
        }

    class Produce(Base) :
        target = '{File}.dut'
        def cmd() :
            print(f'{target}-{step}') # use step to trigger modifications

    class Chk(Base) :
        targets = {
            'REF_OK'  :  '{File}.chk'
        ,   'NEW_REF' : ('{File}.new','phony')
        }
        deps = {
            'DUT' : '{File}'
        }
        side_deps = {
            'REF' : '{File}.ref' # Set as side_deps to be optionnal, so that it is possible to add new ref
        }
        def cmd() :
            try                      : ref_crc = open(REF).read().strip()
            except FileNotFoundError : ref_crc = None
            dut_crc = open(DUT).read().strip()
            print(dut_crc,file=open(REF_OK,'w'))
            if dut_crc!=ref_crc :
                print(f'bad ref : {dut_crc} != {ref_crc}',file=sys.stderr)
                open(NEW_REF,'w')

    class ExpandRef(Base) :
        targets = { 'REF'  : '{File*}.ref' }
        deps    = { 'REFS' : 'refs'        }
        def cmd() :
            for l in open(REFS) :
                file,crc = l.split()
                print(crc,file=open(REF(file),'w'))

    class Update(Base) :
        force = True
        targets = {
            'TGT' : '{File}.update'
        }
        side_targets = {
            'REFS' : ( '{File}'     , 'source_ok','incremental' )
        ,   'NEW'  : ( '{Any*}.new' , 'ignore'                  )
        }
        side_deps = {
            'CHK' : ( '{Any*}.chk' , 'ignore_error' )
        }
        def cmd():
            new_re     = re.compile(NEW.reg_expr)
            new_refs   = ''
            known_refs = set()
            for l in open(REFS) :
                file,ref_crc = l.split()
                try    : dut_crc = open(CHK(file)).read().strip()
                except : dut_crc = None
                new_refs += f'{file} {dut_crc}\n'
                known_refs.add(file)
            for path,dirs,files in os.walk('.') :
                if path=='.' : dirs.remove('LMAKE') # dont look into admin dir, /!\ dirs must be modified in place for it to be seen by os.walk
                path_s = (path+'/')[2:]             # remove prefix './' (but removeprefix is not available in python3.6)
                for name in files :
                    file_new = path_s+name
                    match    = new_re.fullmatch(file_new)
                    if not match : continue
                    file = match.groupdict()['Any']
                    if file in known_refs : continue
                    dut_crc   = open(CHK(file)).read().strip()
                    new_refs += f'{file} {dut_crc}\n'
                    os.unlink(file_new)
            open(TGT,'w')
            open(REFS,'w').write(new_refs)

else :

    import ut

    print('1.dut 1.dut-bad',file=open('refs'   ,'w'))
    print('step=1'         ,file=open('step.py','w'))
    #
    # udpate
    #
    ut.lmake( 'refs.update' , done=3   , may_rerun=2 , failed=1        )
    ut.lmake( '1.dut.chk'   , done=2                                   ) # refs has been updated
    ut.lmake( '2.dut.chk'   , done=1   ,               failed=1 , rc=1 ) # no ref available
    ut.lmake( 'refs.update' , steady=1 ,                               ) # refs added

    print('step=2',file=open('step.py','w'))
    ut.lmake( 'refs.update' , done=3   , failed=2 , steady=1 , was_failed=2 ) # refs recomputed
    ut.lmake( '1.dut.chk'   , done=2                                        ) # refs has been updated