# =============================================================================
#
#  Copyright (c) Kitware, Inc.
#  All rights reserved.
#  See LICENSE.txt for details.
#
#  This software is distributed WITHOUT ANY WARRANTY; without even
#  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
#  PURPOSE.  See the above copyright notice for more information.
#
# =============================================================================

import os
import shutil
import sys

import smtk
import smtk.attribute
import smtk.operation
import smtk.project
import smtk.resource
import smtk.testing

PROJECT_NAME = 'foam.windtunnel'
OP_SUCCEEDED = int(smtk.operation.Operation.Outcome.SUCCEEDED)


class TestSetupBlockMesh(smtk.testing.TestCase):
    def setUp(self):
        smtk.workflows_folder = os.path.join(smtk.testing.SOURCE_DIR, 'simulation-workflows')

        # Initialize resource & operation managers
        self.res_manager = smtk.resource.Manager.create()
        self.op_manager = smtk.operation.Manager.create()

        smtk.attribute.Registrar.registerTo(self.res_manager)
        smtk.attribute.Registrar.registerTo(self.op_manager)

        smtk.operation.Registrar.registerTo(self.op_manager)
        self.op_manager.registerResourceManager(self.res_manager)

        self.proj_manager = smtk.project.Manager.create(self.res_manager, self.op_manager)
        smtk.project.Registrar.registerTo(self.proj_manager)

        self.proj_manager.registerProject(PROJECT_NAME, set(), set(), '1.0.0')

        self.managers = smtk.common.Managers.create()
        self.managers.insert_or_assign(self.res_manager)
        self.managers.insert_or_assign(self.op_manager)
        self.managers.insert_or_assign(self.proj_manager)
        self.op_manager.setManagers(self.managers)

    def tearDown(self):
        self.res_manager = None
        self.op_manager = None
        self.proj_manager = None

    def test_setup(self):
        """"""
        # Read the project generated by the setup_project test
        project_dir = os.path.join(smtk.testing.TEMP_DIR, 'python', 'test_create')
        project_file = os.path.join(project_dir, 'test_create.project.smtk')

        read_op = self.op_manager.createOperation('smtk::project::Read')
        read_op.parameters().findFile('filename').setValue(project_file)
        read_result = read_op.operate()
        read_outcome = read_result.findInt('outcome').value()
        self.assertEqual(read_outcome, OP_SUCCEEDED, 'read project outcome {}'.format(read_outcome))

        project = read_result.findResource('resourcesCreated').value()
        self.assertIsNotNone(project, 'project is null')

        # Import the test operation (SetupBlockMesh)
        import_op = self.op_manager.createOperation('smtk::operation::ImportPythonOperation')
        self.assertIsNotNone(import_op)

        path = os.path.join(
            smtk.testing.SOURCE_DIR, 'smtk/simulation/windtunnel/operations/blockmesh.py')
        self.assertTrue(os.path.exists(path), 'operation file not found: {}'.format(path))

        import_op.parameters().findFile("filename").setValue(path)
        import_res = import_op.operate()
        import_outcome = import_res.findInt('outcome').value()
        self.assertEqual(import_outcome, OP_SUCCEEDED,
                         'import python op outcome {}'.format(import_outcome))

        # Instantiate and run the blockMesh operation
        op_name = import_res.findString('unique_name').value()
        setup_op = self.op_manager.createOperation(op_name)
        self.assertIsNotNone(setup_op, 'BlockMesh operation is null')
        setup_op.parameters().associate(project)
        setup_op.parameters().findString('run').setIsEnabled(False)  # don't run OpemFOAM app
        setup_result = setup_op.operate()
        setup_outcome = setup_result.findInt('outcome').value()
        if setup_outcome != OP_SUCCEEDED:
            print(setup_op.log().convertToString())
            self.assertTrue(False, 'operation outcome {}'.format(setup_outcome))

        # Check for generated files
        case_dir = os.path.join(project_dir, 'foam/blockMesh')
        rel_paths = ['system/controlDict', 'system/blockMeshDict',
                     'constant/include/blockMeshConfig']
        for rel_path in rel_paths:
            path = os.path.join(case_dir, rel_path)
            self.assertTrue(os.path.exists(path))

        # Create a fake "polyMesh" folder for downstream testing
        mesh_dir = os.path.join(case_dir, 'constant/polyMesh')
        if not os.path.exists(mesh_dir):
            os.makedirs(mesh_dir)
        readme_path = os.path.join(mesh_dir, 'placeholder.txt')
        with open(readme_path, 'w') as fp:
            fp.write('Placeholder file for internal testing.\n')


if __name__ == '__main__':
    smtk.testing.process_arguments()
    smtk.testing.main()
