#!/usr/bin/env python

from __future__ import print_function, unicode_literals

import argparse
import difflib
import logging
import os
import subprocess
import sys
import tempfile
from functools import reduce

logging.basicConfig(format='%(message)s', level=logging.INFO)


# Python 2 `unicode` was renamed `str` in Python 3.  To consistently support
# both, define `unicode` to be `str` when using Python 3.  Once we can drop
# Python 2 support, delete this and change all uses of `unicode` to `str`.
# (Currently, this is only here to avoid a python_lint failure from unicode
# references below.)
if sys.version_info[0] >= 3:
    unicode = str


class RoundTripTask(object):
    def __init__(self, input_filename, action, swift_syntax_test,
                 skip_bad_syntax):
        assert action == '-round-trip-parse' or action == '-round-trip-lex'
        if sys.version_info[0] < 3:
            assert type(input_filename) == unicode
        assert type(swift_syntax_test) == str

        assert os.path.isfile(input_filename), \
            "Input file {} is not accessible!".format(input_filename)
        assert os.path.isfile(swift_syntax_test), \
            "{} tool is not accessible!".format(swift_syntax_test)
        self.input_filename = input_filename
        self.action = action
        self.swift_syntax_test = swift_syntax_test
        self.skip_bad_syntax = skip_bad_syntax
        self.returncode = None
        self.stdout = None
        self.stderr = None

    @property
    def test_command(self):
        return [self.swift_syntax_test, self.action,
                '-input-source-filename', self.input_filename]

    def run(self):
        command = self.test_command
        logging.debug(' '.join(command))
        self.output_file = tempfile.NamedTemporaryFile('w', delete=False)
        self.stderr_file = tempfile.NamedTemporaryFile('w', delete=False)

        process = subprocess.Popen(command, stdout=self.output_file,
                                   stderr=self.stderr_file)
        process.wait()
        self.returncode = process.returncode

        self.output_file.close()
        self.stderr_file.close()

        with open(self.output_file.name, 'rb') as stdout_in:
            self.stdout = stdout_in.read()
        with open(self.stderr_file.name, 'rb') as stderr_in:
            self.stderr = stderr_in.read()

        os.remove(self.output_file.name)
        os.remove(self.stderr_file.name)

        if self.returncode != 0:
            if self.skip_bad_syntax:
                logging.warning('---===WARNING===--- Lex/parse had error'
                                ' diagnostics, so not diffing. Skipping'
                                ' this file due to -skip-bad-syntax.')
                logging.error(' '.join(command))
                return None
            else:
                logging.error('---===ERROR===--- Lex/parse had error'
                              ' diagnostics, so not diffing.')
                logging.error(' '.join(command))
                logging.error(self.stdout)
                logging.error(self.stderr)
                raise RuntimeError()

        contents = ''.join(map(lambda l: l.decode('utf-8', errors='replace'),
                               open(self.input_filename, 'rb').readlines()))
        stdout_contents = self.stdout.decode('utf-8', errors='replace')

        if contents == stdout_contents:
            return None

        lines = difflib.unified_diff(contents, stdout_contents,
                                     fromfile=self.input_filename,
                                     tofile='-')
        diff = '\n'.join(line for line in lines)
        return diff if diff else None


def swift_files_in_dir(d):
    swift_files = []
    for root, dirs, files in os.walk(d):
        for basename in files:
            if not basename.endswith('.swift'):
                continue
            abs_file = os.path.abspath(os.path.join(root, basename))
            swift_files.append(abs_file)
    return swift_files


def run_task(task):
    try:
        diff = task.run()
        if diff is not None:
            logging.error('---===ERROR===--- Diff failed!')
            logging.error(' '.join(task.test_command))
            logging.error(diff)
            logging.error('')
            return True
    except RuntimeError as e:
        logging.error(e.message)
        return True
    return False


def main():
    tool_description = '''
Checks for round-trip lex/parse/print compatibility.

Swift's syntax representation should be "full-fidelity", meaning that there is
a perfect representation of what is in the source. When printing a syntax tree
to a file, that file should be identical to the file that was
originally parsed.

This driver invokes swift-syntax-test using -round-trip-lex and
-round-trip-parse on .swift files and .swift files in directories.
'''
    parser = argparse.ArgumentParser(description=tool_description)
    parser.add_argument('--directory', '-d', action='append',
                        dest='input_directories', default=[],
                        help='Add a directory, searching for .swift files'
                             ' within')
    parser.add_argument('--file', '-f', action='append',
                        dest='individual_input_files', default=[],
                        help='Add an individual file to test')
    parser.add_argument('--swift-syntax-test', '-t', required=True,
                        dest='tool_path',
                        help='Absolute path to the swift-syntax-test tool')
    parser.add_argument('--skip-bad-syntax',
                        action='store_true',
                        default=False,
                        help="Skip files that caused lex or parse diagnostics"
                             " to be emitted")

    args = parser.parse_args()

    dir_listings = [swift_files_in_dir(d) for d in args.input_directories]
    all_input_files = [filename for dir_listing in dir_listings
                       for filename in dir_listing]
    all_input_files += args.individual_input_files
    if sys.version_info[0] < 3:
        all_input_files = [f.decode('utf-8') for f in all_input_files]

    if len(all_input_files) == 0:
        logging.error('No input files!')
        sys.exit(1)

    if not os.path.isfile(args.tool_path):
        raise RuntimeError("Couldn't find swift-syntax-test at {}"
                           .format(args.tool_path))

    lex_tasks = [RoundTripTask(filename, '-round-trip-lex', args.tool_path,
                               args.skip_bad_syntax)
                 for filename in all_input_files]
    parse_tasks = [RoundTripTask(filename, '-round-trip-parse', args.tool_path,
                                 args.skip_bad_syntax)
                   for filename in all_input_files]

    failed = reduce(lambda a, b: a or b,
                    map(run_task, lex_tasks + parse_tasks))
    sys.exit(1 if failed else 0)


if __name__ == '__main__':
    main()
