__author__ = 'jez'

import eodatasets.type as ptype
import pathlib
import atexit
import os
import shutil
import tempfile


def assert_same(o1, o2, prefix=''):
    """
    Assert the two are equal.

    Compares property values one-by-one recursively to print friendly error messages.

    (ie. the exact property that differs)

    :type o1: object
    :type o2: object
    :raises: AssertionError
    """

    def _compare(k, val1, val2):
        assert_same(val1, val2, prefix=prefix + '.' + str(k))

    if isinstance(o1, ptype.SimpleObject):
        assert o1.__class__ == o2.__class__, "Differing classes %r: %r and %r" \
                                             % (prefix, o1.__class__.__name__, o2.__class__.__name__)

        for k, val in o1.items_ordered(skip_nones=False):
            _compare(k, val, getattr(o2, k))
    elif isinstance(o1, list) and isinstance(o2, list):
        assert len(o1) == len(o2), "Differing lengths: %s" % prefix

        for i, val in enumerate(o1):
            _compare(i, val, o2[i])
    elif isinstance(o1, dict) and isinstance(o2, dict):
        assert len(o1) == len(o2), "Differing lengths: %s\n\t%r\n\t%r" % (prefix, o1, o2)

        for k, val in o1.items():
            assert k in o2, "%s[%r] is missing.\n\t%r\n\t%r" % (prefix, k, o1, o2)
            _compare(k, val, o2[k])

    elif o1 != o2:
        print repr(o1)
        print repr(o2)
        raise AssertionError("Mismatch for property %r:  %r != %r" % (prefix, o1, o2))


def write_files(file_dict):
    """
    Convenience method for writing a bunch of files to a temporary directory.

    Dict format is "filename": "text content"

    If content is another dict, it is created recursively in the same manner.

    writeFiles({'test.txt': 'contents of text file'})

    :type file_dict: dict
    :rtype: pathlib.Path
    :return: Created temporary directory path
    """
    containing_dir = tempfile.mkdtemp(suffix='neotestrun')
    _write_files_to_dir(containing_dir, file_dict)

    def remove_if_exists(path):
        if os.path.exists(path):
            shutil.rmtree(path)

    atexit.register(remove_if_exists, containing_dir)
    return pathlib.Path(containing_dir)


def _write_files_to_dir(directory_path, file_dict):
    """
    Convenience method for writing a bunch of files to a given directory.

    :type directory_path: str
    :type file_dict: dict
    """
    for filename, contents in file_dict.items():
        path = os.path.join(directory_path, filename)
        if isinstance(contents, dict):
            os.mkdir(path)
            _write_files_to_dir(path, contents)
        else:
            with open(path, 'w') as f:
                if isinstance(contents, list):
                    f.writelines(contents)
                elif isinstance(contents, (str, unicode)):
                    f.write(contents)
                else:
                    raise Exception('Unexpected file contents: %s' % type(contents))


def temp_dir():
    """
    Create and return a temporary directory that will be deleted automatically on exit.

    :rtype: str
    """
    return write_files({})


def temp_file(suffix=""):
    """
    Get a temporary file path that will be cleaned up on exit.

    Simpler than NamedTemporaryFile--- just a file path, no open mode or anything.
    :return:
    """
    f = tempfile.mktemp(suffix=suffix)

    def permissive_ignore(file_):
        if os.path.exists(file_):
            os.remove(file_)

    atexit.register(permissive_ignore, f)
    return f


def file_of_size(path, size_mb):
    """
    Create a blank file of the given size.
    """
    with open(path, "wb") as f:
        f.seek(size_mb * 1024 * 1024 - 1)
        f.write("\0")

@@ -24,40 +24,32 @@
 ort 
-eodatasets.type as ptype
+atexit%0Aimport os
 %0Aimport 
 path
@@ -48,23 +48,22 @@
 ort 
-pathlib
+shutil
 %0Aimport 
 atex
@@ -54,38 +54,40 @@
 util%0Aimport 
-a
 te
-xit
+mpfile
 %0Aimport 
 os%0Aimport sh
@@ -78,39 +78,59 @@
 ort 
-o
+sy
 s%0A
+%0A
 import 
-shutil%0Aimport tempfil
+pathlib%0A%0Aimport eodatasets.type as ptyp
 e%0A%0A%0A
@@ -1369,42 +1369,72 @@
     
-print repr(o1)%0A        print repr(
+sys.stderr.write(%22%25r%5Cn%22 %25 o1)%0A        sys.stderr.write(%22%25r%5Cn%22 %25 
 o2)%0A

Write test errors to stderr.