#!/usr/bin/python3

import os
import shutil
import signal
import string
import subprocess
import sys
import xml.etree.ElementTree
from distutils.spawn import find_executable


def findparentfiles(fname):
    filelist = []
    newlist = []
    args = ['grep', '-rl', '--exclude-dir=.git', fname]
    proc = subprocess.run(args, capture_output=True)
    data = proc.stdout.decode()
    if proc.returncode != 0:
        return filelist
    for filename in data.splitlines():
        if filename.endswith('.yaml') and '/' not in filename:
            filelist.append(filename)
        else:
            newlist = findparentfiles(filename)
            for tempname in newlist:
                filelist.append(tempname)
    return filelist


jjb_cmd = find_executable('jenkins-jobs') or sys.exit('jenkins-jobs is not found.')
jjb_args = [jjb_cmd]

jjb_user = os.environ.get('JJB_USER')
jjb_password = os.environ.get('JJB_PASSWORD')
if jjb_user is not None and jjb_password is not None:
    jenkins_jobs_ini = ('[job_builder]\n'
                        'ignore_cache=True\n'
                        'keep_descriptions=False\n'
                        '\n'
                        '[jenkins]\n'
                        'user=%s\n'
                        'password=%s\n'
                        'url=https://mbedtls.trustedfirmware.org/\n' % (jjb_user, jjb_password))
    with open('jenkins_jobs.ini', 'w') as f:
        f.write(jenkins_jobs_ini)
    jjb_args.append('--conf=jenkins_jobs.ini')

jjb_test_args = list(jjb_args)
jjb_delete_args = list(jjb_args)

# !!! "update" below and through out this file is replaced by "test" (using sed)
# !!! in the sanity-check job.
main_action = 'update'
jjb_args.extend([main_action, 'template.yaml'])
jjb_test_args.extend(['test', '-o', 'out/', 'template.yaml'])
jjb_delete_args.extend(['delete'])

if main_action == 'test':
    # Dry-run, don't delete jobs.
    jjb_delete_args.insert(0, 'echo')

try:
    git_args = ['git', 'diff', '--raw',
                os.environ.get('GIT_PREVIOUS_COMMIT'),
                os.environ.get('GIT_COMMIT')]
    proc = subprocess.run(git_args, capture_output=True)
except (OSError, ValueError) as e:
    raise ValueError("%s" % e)

data = proc.stdout.decode()
if proc.returncode != 0:
    raise ValueError("command has failed with code '%s'" % proc.returncode)

filelist = []
deletelist = []
files = []
for line in data.splitlines():
    # Format of the git-diff; we only need OPERATION and FILE1
    #
    # :<OLD MODE> <NEW MODE> <OLD REF> <NEW REF> <OPERATION> <FILE1> <FILE2>
    elems = line.split()
    operation = elems[4][0]
    filename = elems[5]

    if filename.endswith('.yaml') and '/' not in filename:
        # No point trying to test deleted jobs because they don't exist any
        # more.
        if operation == 'D':
            deletelist.append(filename[:-5])
            continue
        # operation R100 is 100% rename, which means sixth element is the renamed file
        if operation == 'R':
            filename = elems[6]
            # delete old job name
            deletelist.append(elems[5][:-5])
        filelist.append(filename)
    else:
        files = findparentfiles(filename)
        for tempname in files:
            filelist.append(tempname)

# Remove duplicate entries in the list
filelist = list(set(filelist))

for conf_filename in filelist:
    with open(conf_filename) as f:
        buffer = f.read()
        template = string.Template(buffer)
        buffer = template.safe_substitute(
            AUTH_TOKEN=os.environ.get('AUTH_TOKEN'),
            LT_QCOM_KEY=os.environ.get('LT_QCOM_KEY'),
            LAVA_USER=os.environ.get('LAVA_USER'),
            LAVA_TOKEN=os.environ.get('LAVA_TOKEN'))
        with open('template.yaml', 'w') as f:
            f.write(buffer)
        try:
            proc = subprocess.run(jjb_args, capture_output=True)
        except (OSError, ValueError) as e:
            raise ValueError("%s" % e)

        data = proc.stdout.decode()
        stderr = proc.stderr.decode()
        if proc.returncode != 0:
            print(f"STDOUT: {data}")
            print(f"STDERR: {stderr}")
            raise ValueError("command has failed with code '%s'" % proc.returncode)

        try:
            shutil.rmtree('out/', ignore_errors=True)

            proc = subprocess.run(jjb_test_args, capture_output=True)
            data = proc.stdout.decode()
            if proc.returncode != 0:
                raise ValueError("command has failed with code '%s'" % proc.returncode)

            proc = subprocess.run(['ls', 'out/'], capture_output=True)
            data = proc.stdout.decode()
            if proc.returncode != 0:
                raise ValueError("command has failed with code '%s'" % proc.returncode)

            for filename in data.splitlines():
                # old job conf might have been removed because the job is now generated through the template
                # do not delete the job in this case
                if filename in deletelist:
                    deletelist.remove(filename)

                conf_name=os.path.splitext(conf_filename)[0]
                conf_name=conf_name[:len(filename)]
                if not filename.startswith(conf_name):
                    raise ValueError("Job name %s does not match the file it is in: %s" % (filename, conf_name))
                try:
                    xmlroot = xml.etree.ElementTree.parse('out/' + filename).getroot()
                    disabled = next(xmlroot.iterfind('disabled')).text
                    if disabled != 'true':
                        continue
                    displayName = next(xmlroot.iterfind('displayName')).text
                    if displayName != 'DELETE ME':
                        continue
                except:
                    continue

                deletelist.append(filename)

        except (OSError, ValueError) as e:
            raise ValueError("%s" % e)

        shutil.rmtree('out/', ignore_errors=True)
        os.remove('template.yaml')


for deletejob in deletelist:
    delete_args = list(jjb_delete_args)
    delete_args.extend([deletejob])
    try:
        proc = subprocess.run(delete_args, capture_output=True)
        data = proc.stdout.decode()
        if proc.returncode != 0:
            raise ValueError("command has failed with code '%s'" % proc.returncode)
        print(data)
    except (OSError, ValueError) as e:
        raise ValueError("%s" % e)

if os.path.exists('jenkins_jobs.ini'):
    os.remove('jenkins_jobs.ini')

