# 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 os
import shutil
from functools import partial

import pytest
import numpy as np
import h5py

import damask

@pytest.fixture
def res_path(res_path_base):
    """Directory containing testing resources."""
    return res_path_base/'grid_mech_consistency'


def h5py_compare_files(iterator,asserter,
                       fname_reference,fname_current):
    ref=h5py.File(fname_reference,'r')
    cur=h5py.File(fname_current,'r')
    for (path,dset) in iterator(ref):
       if path.startswith('setup'): continue
       if len(dset.dtype) > 0:
           for e in dset.dtype.fields:
               assert np.all(dset[e]==cur[path][e])
       else:
           asserter(dset,cur[path])

# this class attribute is not reset when using pytest-repeat
ref = {}

@pytest.mark.parametrize('solver',['spectral_basic','spectral_polarization','spectral_Galerkin','FEM'])
@pytest.mark.parametrize('grid, load, material', [('g_333', 'tensionY', 'material_elast'),
                                                  ('g_444', 'tensionX', 'material_plast'),])
def test_grid_mech_consistency(res_path,tmp_path,copy_files,h5py_dataset_iterator,assert_allclose,
                               solver,grid,load,material):
    job = f'{grid}_{load}_{material}'

    copy_files(res_path,tmp_path,[f'{grid}.vti',f'{material}.yaml'])
    l = damask.LoadcaseGrid.load(res_path/f'{load}.yaml')
    l['solver']['mechanical'] = solver
    l.save(tmp_path/f'{load}.yaml')

    damask.util.run(f'damask_grid -l {load}.yaml -g {grid}.vti -m {material}.yaml',
                    wd=tmp_path)

    if job in ref:
        h5py_compare_files(h5py_dataset_iterator,
                           partial(assert_allclose,atol=1e-2),
                           ref[job],
                           tmp_path/f'{job}.hdf5')
    else:
        ref[job] = tmp_path/f'{job}.hdf5'
