# SPDX-License-Identifier: AGPL-3.0-or-later
# Copyright 2024-2025 Max-Planck-Institut für Nachhaltige Materialien GmbH
# Copyright 2011-2024 Max-Planck-Institut für Eisenforschung GmbH
#
# DAMASK is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
import pytest
import numpy as np

from damask import YAML
from damask import Rotation
from damask import Orientation

def test_init_keyword():
    assert YAML(p=4)['p'] == 4

@pytest.mark.parametrize('config',[{'p':1},'{p: 1}'])
def test_init_config(config):
    assert YAML(config)['p'] == 1

@pytest.mark.parametrize('config',[{'p':1},'{p: 1}'])
def test_init_both(config):
    assert YAML(config,p=2)['p'] == 2

@pytest.mark.parametrize('flow_style',[None,True,False])
def test_load_save_path(tmp_path,flow_style):
    config = YAML()
    config['A'] = 1
    config['B'] = [2,3]
    config.save(tmp_path/'config.yaml',default_flow_style=flow_style)
    assert YAML.load(tmp_path/'config.yaml') == config

def test_load_save_file(tmp_path):
    config = YAML()
    config['A'] = 1
    config['B'] = [2,3]
    with open(tmp_path/'config.yaml','w') as f:
        config.save(f)
    with open(tmp_path/'config.yaml') as f:
        assert YAML.load(f) == config

def test_load_invalid(tmp_path):
    with open(tmp_path/'config.yaml','w') as f:
        f.write('[1, 2, 3]') # valid YAML
    with pytest.raises(TypeError):
        YAML.load(tmp_path/'config.yaml')

def test_add_remove():
    dummy = {'hello':'world','foo':'bar'}
    config = YAML()
    config |= dummy
    assert config == YAML() | dummy
    config = config.delete(dummy)
    assert config == YAML()
    assert (config |      dummy ).delete(        'hello'            ) == config | {'foo':'bar'}
    assert (config |      dummy ).delete([       'hello',  'foo'   ]) == config
    assert (config | YAML(dummy)).delete({       'hello':1,'foo':2 }) == config
    assert (config | YAML(dummy)).delete(YAML({'hello':1        }))   == config | {'foo':'bar'}

def test_repr(tmp_path):
    config = YAML()
    config['A'] = 1
    config['B'] = [2,3]
    with open(tmp_path/'config.yaml','w') as f:
        f.write(config.__repr__())
    assert YAML.load(tmp_path/'config.yaml') == config

def test_utf8_minimal_escaping(tmp_path):
    config = YAML()
    config['key'] = 'Ælżβéth 🌸 Михаи́л ᚠᛚᚨ🧙‍♂️'
    repr = config.__repr__()
    assert r'\x' not in repr
    assert r'\u' not in repr

def test_numpy(tmp_path):
    assert YAML({'A':np.ones(3,'i'), 'B':np.ones(1)[0]}).__repr__() == \
           YAML({'A':[1,1,1],        'B':1.0}).__repr__()

def test_abstract_is_valid():
    with pytest.raises(NotImplementedError):
        YAML().is_valid

def test_abstract_is_complete():
    with pytest.raises(NotImplementedError):
        YAML().is_complete

@pytest.mark.parametrize('data',[Rotation.from_random(),Orientation.from_random(lattice='cI')])
def test_rotation_orientation(data):
    assert str(YAML(a=data)) == str(YAML(a=data.as_quaternion()))

def test_initialize():
    yml = """
    a:
        - 1
        - 2
    """
    assert YAML(yml) == YAML('{"a":[1,2]}') == YAML(a=[1,2]) == YAML(dict(a=[1,2]))
