# =============================================================================
#
#  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.markup
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.markup.Registrar.registerTo(self.res_manager)
        smtk.markup.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.project_dir = os.path.join(smtk.testing.TEMP_DIR, 'python', 'test_create')

        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_import(self):
        project = self._read_project()
        self._import_model(project)
        self._write_project(project)

    def _read_project(self, clear_models=True):
        """"""
        # Read the project generated by the setup_project test
        project_file = os.path.join(self.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')

        if not clear_models:
            return project

        return project

    def _import_model(self, project):
        """"""
        # Import the test operation
        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/import_model.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 import_model operation
        op_name = import_res.findString('unique_name').value()
        model_op = self.op_manager.createOperation(op_name)
        self.assertIsNotNone(model_op, 'ImportModel operation is null')

        model_op.parameters().associate(project)

        model_file = os.path.join(smtk.testing.DATA_DIR, 'model/3d/stl/prism5.stl')
        self.assertTrue(os.path.exists(model_file), 'model file not found {}'.format(model_file))
        model_op.parameters().findFile('filename').setValue(model_file)
        model_op.parameters().findVoid('overwrite').setIsEnabled(True)  # for idempotence

        # Import model file to create markup-session resource
        model_result = model_op.operate()
        model_outcome = model_result.findInt('outcome').value()
        if model_outcome != OP_SUCCEEDED:
            print(model_op.log().convertToString())
            self.assertTrue(False, 'import model op outcome {}'.format(model_outcome))

        # Verify that project contains model resource
        resource_set = project.resources().findByRole('model')
        self.assertEqual(len(resource_set), 1, 'Wrong number of model resources; should be 1')

    def _write_project(self, project):
        write_op = self.op_manager.createOperation('smtk::project::Write')
        self.assertIsNotNone(write_op)
        write_op.parameters().associate(project)
        write_result = write_op.operate()
        write_outcome = write_result.findInt('outcome').value()
        self.assertEqual(write_outcome, OP_SUCCEEDED,
                         'write project op outcome {}'.format(write_outcome))


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