import argparse
import csv
import os
import re
import shutil
import subprocess


# Find the most recent analysis of the named project and record its
# Analysis ID. Note that there may be multiple projects with the same
# name, in which case information for all of them will be recorded.
def find_last_analysis(hubaddr, project_name, savedir):
    curl_cmd = ['curl']

    project_search_csv = '{0}/project_search.csv?query=project%3D"{1}"&scope=all'.format(hubaddr, project_name)

    result_fname='overall_results.csv'
    search_fname='project_search_results.csv'

    search_cmdline = curl_cmd + ['-o',search_fname] + [project_search_csv]
    subprocess.check_call(search_cmdline)
    search_results=[]

    no_analysis = 'No most recent analysis found. Either: a) the project has '\
                  + 'no analyses or b) you do not have ANALYSIS_EXISTS '\
                  + 'permission for the most recent analysis.'
    num_results = 0
    with open(search_fname, 'r', newline='') as csvfile:
        search_results = csv.DictReader(csvfile)

        with open(result_fname, 'w', newline='') as outfile:
            fieldnames = ('project id',
                          'most recent analysis id',
                          'notes',)
            writer = csv.DictWriter(outfile, fieldnames=fieldnames)
            writer.writeheader()
            for row in search_results:
                result_match = re.search(r'.*/(?P<rtype>analysis|project)/(?P<rid>\d+)\.csv',
                                         row['url'])
                # If the last column of a result line is neither a project
                # URL nor an analysis URL, report a problem.
                if result_match is None:
                    print('Unexpected result {0} in {1}.'.format(str(row),
                                                                 result_fname))
                    continue

                num_results += 1
                # An analysis URL identifies the most recent analysis.
                if result_match.group('rtype')=='analysis':
                    writer.writerow(
                        {'most recent analysis id':result_match.group('rid')})
                    # A project URL indicates that the most recent analysis 
                    # of that project cannot be reported.
                else:
                    writer.writerow(
                        {'project id':result_match.group('rid'),
                         'notes':no_analysis})

    if num_results==0:
        # If no results, report and exit.
        print('No projects with URL-encoded name', project_name, 'were found.')
        print('This may indicate one or more of the following.')
        print('- The project name was not specified correctly (remember to URL-encode).') 
        print('- You do not have PROJECT_EXISTS permission for the specified project.')
        exit(1)

    print('Found {0} project(s) with URL-encoded name {1}.'.format(num_results,
                                                                   project_name))
    print('Your results are in {0}/{1}'.format(savedir,result_fname))
    

# Set up.
def go():
    parser = argparse.ArgumentParser(
        description=('Find the most recent analysis of '
                     + 'a project on a CodeSonar hub, '
                     + 'as specified by the command-line arguments.'))
        
    parser.add_argument("hub",
                        help="The hub URL.")
    parser.add_argument("pname",
                        help="The project  name; must be URL-encoded.")
    parser.add_argument("outdir",
                        help="The save directory.")
    args = parser.parse_args()

    allargs = (args.hub, args.pname, args.outdir)
    if not any([a is None for a in allargs]):
        if os.path.isdir(args.outdir):
            print('Output directory {0} exists, deleting and recreating.'.format(args.outdir))
            shutil.rmtree(args.outdir)
        os.mkdir(args.outdir)
        os.chdir(args.outdir)

        find_last_analysis(*allargs)

go()
