import pytest

import copy
import json
from imecilabt_utils.utils import deep_update_dict


def test_deep_update_dict_1():
    orig = {
        'a': 'aa',
        'b': 2,
        'c': 'cc',
        'd': ['dd'],
    }

    extra = {
        'a': 'aachanged',
        'b': 'bb',
        'd': 4,
        'e': 'ee',
    }

    expected = {
        'a': 'aachanged',
        'b': 'bb',
        'c': 'cc',
        'd': 4,
        'e': 'ee',
    }

    actual = copy.deepcopy(orig)
    deep_update_dict(actual, extra)

    # Use json so that keys are sorted (and indent to easily show differences)
    actual_json = json.dumps(actual, sort_keys=True, indent=4)
    expected_json = json.dumps(expected, sort_keys=True, indent=4)

    print("\nactual  ={}".format(actual_json))
    print("expected={}".format(expected_json))

    assert actual_json == expected_json


def test_deep_update_dict_2():
    orig = {
        'a': {
            'b': {
                'c1': 'c1',
                'c2': 'c2',
                'c3': 'c3'
            }
        }
    }

    extra = {
        'a': {
            'b': {
                'c1': 'c1c',
                'c2': 2,
                'c4': 'c4'
            }
        }
    }

    expected = {
        'a': {
            'b': {
                'c1': 'c1c',
                'c2': 2,
                'c3': 'c3',
                'c4': 'c4'
            }
        }
    }

    actual = copy.deepcopy(orig)
    deep_update_dict(actual, extra)

    # Use json so that keys are sorted (and indent to easily show differences)
    actual_json = json.dumps(actual, sort_keys=True, indent=4)
    expected_json = json.dumps(expected, sort_keys=True, indent=4)

    print("\nactual  ={}".format(actual_json))
    print("expected={}".format(expected_json))

    assert actual_json == expected_json


def test_deep_update_dict_all():
    orig = {
        'a': 'aa',
        'b': 1,
        'c': {
            'o': 'oo',
            'p': 8,
            'q': {
                'qa': 'ok'
            },
            'qq': {
                'qqb': 'ok'
            }
        },
        'd': ['x', 'y', {'z' : 'zz' }]
    }

    extra = {
        'ag': 'ggg',
        'b': 2,
        'c': {
            'o': 'oochanged',
            'pp': 88,
            'q': {
                'qa': 'stillok',
                'qa2': 'alsook'
            },
            'qq': {
                'qqb': {'A': 'A'},
                'qqbb': {'B': 'B'}
            }
        },
        'd': ['x', {'p': 'pp'}]
    }

    expected = {
        'a': 'aa',
        'ag': 'ggg',
        'b': 2,
        'c': {
            'o': 'oochanged',
            'pp': 88,
            'p': 8,
            'q': {
                'qa': 'stillok',
                'qa2': 'alsook'
            },
            'qq': {
                'qqb': {'A': 'A'},
                'qqbb': {'B': 'B'}
            }
        },
        'd': ['x', {'p': 'pp'}]
    }

    actual = copy.deepcopy(orig)
    deep_update_dict(actual, extra)

    # Use json so that keys are sorted (and indent to easily show differences)
    actual_json = json.dumps(actual, sort_keys=True, indent=4)
    expected_json = json.dumps(expected, sort_keys=True, indent=4)

    print("\nactual  ={}".format(actual_json))
    print("expected={}".format(expected_json))

    assert actual_json == expected_json
