#!/usr/bin/python
import argparse
import logging
import os
import re
import sys

#declaration_match = re.compile(r'^entity (?P<entity_name>.*?) is$.*?^end (?:(?P=entity_name)|entity);$', re.MULTILINE | re.DOTALL)
declaration_match = re.compile(r'^entity (?P<entity_name>.*?) is$.*?^end (?P=entity_name);$', re.MULTILINE | re.DOTALL)

def directory_path(string):
    if os.path.isdir(string):
        return string
    else:
        raise NotADirectoryError(string)

def get_parser():
    parser = argparse.ArgumentParser()
    parser.add_argument('-d', '--dest-dir', help='The destination directory to store the entity headers in', type=directory_path)
    parser.add_argument('source_files', nargs='*', type=argparse.FileType('r'))
    parser.add_argument('--pattern', default='{entity_name}_entity.vhd', help='The pattern to use for the destination filename. Available substitutions: {entity_name}.')
    parser.add_argument('-s', '--skip-missing', action='store_true', help='Skip over files missing an entity declaration')
    parser.add_argument('-v', '--verbose', action='count')

    return parser

def parse_header(src_file):
    if m := re.search(declaration_match, src_file.read()):
        return (m.group('entity_name'), m.group(0))
    else:
        return None

if __name__ == '__main__':
    parser = get_parser()
    args = parser.parse_args()

    logging.basicConfig(level=args.verbose)

    for src_file in args.source_files:
        if res := parse_header(src_file):
            (entity_name, declaration) = res
            dest_file_path = os.path.join(args.dest_dir, args.pattern.format_map({'entity_name': entity_name}))
            logging.info(f'Writing header for {entity_name} to {dest_file_path}')

            with open(dest_file_path, 'w') as destfile:
                destfile.write(declaration)
        else:
            errmsg = f'No entity declaration found in {src_file.name}'
            if args.skip_missing:
                logging.warning(errmsg)
            else:
                logging.error(errmsg)
                sys.exit(1)

