# IfcOpenShell - IFC toolkit and geometry engine
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of IfcOpenShell.
#
# IfcOpenShell is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# IfcOpenShell 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell.  If not, see <http://www.gnu.org/licenses/>.

import time
import ifcopenshell
import ifcopenshell.api.owner.settings


class Usecase:
    def __init__(self, file):
        """Creates a new owner history indicating an element was added

        Any object in IFC with a unique ID and name (such as physical products,
        tasks, calendars, etc) may have an owner associated with it. An owner is
        a liable person and/or organisation which a bit of metadata indicating
        whether they have created the object, edited the object, when the change
        was made, and which application they used.

        IFC does not offer a comprehensive specification for version control and
        change tracking, as this is completely out of scope. However this
        similar ability allows IFC to satisfy legal requirements where object
        ownership, responsibilities, and permissions must be specified.
        Recording the owner is mandatory in IFC2X3 but optional in IFC4. It is
        not recommended to store this ownership data in IFC4 unless a legal
        requirement is in place.

        Because owner tracking is mandatory in IFC2X3, be aware that some
        configuration may be required to work correctly. Read on.

        To track the owner, at a minimum we have to know the application that
        the element was authored from, as well as the user (person and
        organisation) that made the change. The IfcOpenShell API is a low level
        software library and will not know what application the API is being
        called from, and nor does it have the responsibility to manage the
        "active user" making edits, which may be as simple as hardcoding it to
        "Bob" or even be as complex as integrationg with a CDE's authentication
        system. As a result, the developer responsible to integrate with
        IfcOpenShell is expected to overload the
        ifcopenshell.api.owner.settings.get_user and
        ifcopenshell.api.owner.settings.get_application functions.

        It is not necessary to call this function directly if you are already
        using other API calls. It is a low level function only available if you
        are writing your own advanced scripts and want to take advantage of the
        easier ownership tracking.

        :return: The newly created IfcOwnerHistory element.
        :rtype: ifcopenshell.entity_instance.entity_instance

        Example:

        .. code:: python

            # Let's imagine we're writing a small script, not large enough to be
            # its own fully branded application. In this case, let's use the
            # default application which is prepopulated with "IfcOpenShell" as
            # the name and version.
            application = ifcopenshell.api.run("owner.add_application", model)

            # Let's imagine we run this as an automated QA process in an
            # architectural firm. However, the results must be signed off by the
            # registered architect who is liable for the project.
            person = ifcopenshell.api.run("owner.add_person", model,
                identification="LPARTEE", family_name="Partee", given_name="Leeable")
            organisation = ifcopenshell.api.run("owner.add_organisation", model,
                identification="AWB", name="Architects Without Ballpens")
            user = ifcopenshell.api.run("owner.add_person_and_organisation", model,
                person=person, organisation=organisation)

            # Let's configure our owner settings to hardcode always returning
            # the application and user. In theory, you could build complex user
            # access control lookup functions here, but this is simple enough.
            ifcopenshell.api.owner.settings.get_user = lambda x: user
            ifcopenshell.api.owner.settings.get_application = lambda x: application

            # We've finished our ownership setup. Now let's start our script and
            # create a space. Notice we don't actually call
            # create_owner_history at all. This is already automatically handled
            # by the API when necessary. Under the hood, the API is actually
            # running this code on the IfcSpace element:
            # element.OwnerHistory = ifcopenshell.api.run("owner.create_owner_history", model)
            space = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcSpace")
        """
        self.file = file
        self.settings = {}

    def execute(self):
        user = ifcopenshell.api.owner.settings.get_user(self.file)
        if self.file.schema != "IFC2X3" and not user:
            return
        application = ifcopenshell.api.owner.settings.get_application(self.file)
        if self.file.schema != "IFC2X3" and not application:
            return
        return self.file.create_entity(
            "IfcOwnerHistory",
            **{
                "OwningUser": user,
                "OwningApplication": application,
                "State": "READWRITE",
                "ChangeAction": "ADDED",
                "LastModifiedDate": int(time.time()),
                "LastModifyingUser": user,
                "LastModifyingApplication": application,
                "CreationDate": int(time.time()),
            },
        )
