#!/usr/bin/env python
#
# by Holger Doebler <stephaho@informatik.hu-berlin.de>
#
# This python script is intended to help in verification of your solution
# of the Sommersemester 2018 Digitale Systeme C Programmierprojekt.
#
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


from __future__ import with_statement
from itertools import chain
import sys

def print_help_message():
    print("""Usage: check_result [-q|-qq] INPUT|SAMPLE_OUTPUT YOUR_OUTPUT

    Depending on the first file given, checks for errors in the file
    given as second argument.

ARGUMENTS (required)
    If the first argument is a sample output file as provided, it
    checks whether SAMPLE_OUTPUT and YOUR_OUTPUT are compatible.

    If the first argument is an input file, check_result will check
    whether YOUR_OUTPUT is a correct 1x2-tiling of the area defined by
    INPUT. Note that check_result will not perform any checks, if
    YOUR_OUTPUT states 'None', i.e., if your 'solution' is that there
    does not exist a 1x2 tiling of the INPUT.

    If YOUR_OUTPUT is either "-" or omitted, it is read from stdin.

OPTIONS
    -q      Only report errors. Suppress output PASSED and FAILED and INFO.
    -qq     Suppress all output. Exit code is the only feedback.

WARNING
    This script is intended to be portable across platforms and python
    versions. IMHO it does not qualify as well-written modern
    python. Use this script as it is. Trying to replicate any of its
    functionality, e.g. reading the input, as part of your solution is
    probably a very bad idea.

EXIT CODES:
    0     Test passed. YOUR_OUTPUT seems to be correct.
    1     Uncaught exception. Please send a bug report.
    2     Invocation / IO error
    10-16 Malicious input file content. Input file itself cannot be correct.
    20    Cannot perform any checks. YOUR_OUTPUT is "None", which might be
          correct.
    21    Test failed. YOUR_OUTPUT is wrong.


Send bug reports and suggestions for improvement to
Holger Doebler <stephaho@informatik.hu-berlin.de>
""")
    sys.exit(2)

verbosity = 2
def pre(s):
    if verbosity > 0:
        print('ERROR: ' + s)

def pri(s):
    if verbosity > 1:
        print(s)

def read_tile_file(path, allow_input_file):
    if path == '-':
        f = sys.stdin
    else:
        try:
            f = open(path)
        except IOError:
            print_help_message()
    with f:
        i = iter(f)
        try:
            l = next(i)
        except UnicodeDecodeError:
            pre('File "%s" contains illegal character.' % (path,))
            sys.exit(15)
        except StopIteration:
            pre('file "%s" seems to be empty.' % path)
            sys.exit(2)
        if l.strip() == 'None':
            try:
                l = next(i)
            except UnicodeDecodeError:
                pre('File "%s" line #%d contains illegal character.' % (path, 1))
                sys.exit(15)
            except StopIteration:
                return ('solution', None)
            pre('file "%s" line "None" followed by further illegal lines.'
                  % path)
            sys.exit(10)
        lines = chain([l], i)
        read_input_file = False
        if allow_input_file:
            read_input_file = True
            try:
                xy = tuple(map(int, l.split()))
                if len(xy) != 2:
                    read_input_file = False
            except ValueError:
                read_input_file = False
        res = set()
        if read_input_file:
            for j,l in enumerate(lines, start=1):
                try:
                    xy = tuple(map(int, l.split()))
                except ValueError:
                    xy = ()
                if len(xy) != 2 or xy[0] < 0 or xy[1] < 0:
                    pre('File %s line #%d does not have the correct '
                          'input file format.' % (path, j))
                    sys.exit(14)
                if xy in res:
                    pre('File "%s" line #%d is a duplicate.' % (path, j))
                    sys.exit(15)
                res.add(xy)
            return ('input', res)
        else:
            for j,l in enumerate(lines, start=1):
                try:
                    (x1,y1),(x2,y2) = tuple((tuple(map(int,x.split()))
                                             for x in l.split(';')))
                    if any([z < 0 for z in (x1,y1,x2,y2)]):
                        raise ValueError
                except ValueError:
                    pre('Illegal line format in file "%s" line #%d.'
                          % (path, j))
                    sys.exit(11)
                if (x1!=x2 and y1!=y2) or (x1==x2 and y1==y2):
                    pre('File "%s" line #%d does not describe a 1x2tile.'
                        % (path, j))
                    sys.exit(12)
                for xy in ((x1,y1),(x2,y2)):
                    if xy in res:
                        pre('Tile in file "%s" line #%d overlaps with '
                              'other tiles in this file.' % (path, j))
                        sys.exit(13)
                    res.add(xy)
            return ('solution', res)

if __name__=='__main__':
    for verb, flag in enumerate(('-qq', '-q')):
        while flag in sys.argv:
            verbosity = verb
            sys.argv.remove(flag)
    if len(sys.argv) == 2:
        sys.argv.append('-')
    if len(sys.argv) != 3:
        print_help_message()
    t1 = read_tile_file(sys.argv[1], True)
    t2 = read_tile_file(sys.argv[2], False)
    if t1[1] == t2[1]:
        pri('PASSED')
        sys.exit(0)
    if t2[1] is None and t1[0] == 'input':
        pri('INFO: "%s" is an input file and "%s" sais "None". Cannot check '
              'whether this is the correct answer.'
              % tuple(sys.argv[1:]))
        sys.exit(20)
    else:
        pri('FAILED')
        sys.exit(21)