# -*- coding: utf-8 -*-
#
#*******************************************************************************
#
#  Copyright 2022 RIEGL Laser Measurement Systems
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
#
#  SPDX-License-Identifier: Apache-2.0
#
#*******************************************************************************
#
"""
Manage point cloud changelog
"""

from ctypes import CFUNCTYPE, byref, c_uint8, c_uint32, c_void_p

from . import library
from . import context
from . import utilities


class Changelog:
    """
    Manage point cloud changelog

    Each database maintains a log of changes made to a point cloud.

    A separate log entry is created for each database transaction or management
    operation. A log entry contains log messages with high-level information
    about the modifications as follows:

      - current transaction number, title, agent, date and time
      - number of data points added, updated, removed
      - list of point attributes affected by point operations
      - list of point attributes added, updated, removed
      - list of metadata entries added, updated, removed
      - modification of level-of-detail parameters
      - management: restore transaction, finalize and vacuum database
      - optional: log messages (some text) provided by client software

    Details like actual point data, attribute definitions or metadata values are
    not recorded.

    Since 2.3.0
    """

    def __init__(self, pointcloud):
        self.context = pointcloud.context
        self.pointcloud = pointcloud

    def append_message(self, message):
        """
        Append text to current log entry

        This function appends text message(s) to the log entry of the current
        database transaction. As with all strings in RDB, the characters are
        expected to be UTF-8 encoded. Line endings are normalized (i.e. CR+LF
        and CR are converted to LF).

        Calling this function while no transaction is active has no effect.

        Since 2.3.0
        """
        self.context.check(
            library.handle.rdb_pointcloud_changelog_append_log_message(
                self.context.handle,
                self.pointcloud.handle,
                utilities.to_rdb_string(message)
            )
        )

    @staticmethod
    def verify_log_entry(entry, method, key):
        """
        Verify log entry signature

        Returns 'False' if:

        - there is no signature for the log entry
        - the signature does not match the log messages
        - a wrong signature encryption key was given

        Otherwise returns 'True'.

        Since 2.3.0
        """
        valid = c_uint32(0)
        if isinstance(key, str):
            key = bytes.fromhex(key)
        key = (c_uint8 * len(key))(*key)
        context.Context.check_cf(
            library.handle.rdb_pointcloud_changelog_verify_log_entry_cf(
                utilities.to_rdb_string(entry),
                c_uint32(method),
                c_uint32(len(key)),
                byref(key),
                byref(valid)
            )
        )
        return valid.value != 0

    def export_to_textfile(self, filename):
        """
        Export changelog to text file

        This function exports the entire changelog to a single text file.
        The file is UTF-8 encoded and text lines are separated by a single
        line feed character (LF, ASCII 0x0A), regardless of the operating
        system the file was created on.

        Since 2.3.0
        """
        library.handle.rdb_pointcloud_changelog_export_to_textfile(
            self.context.handle,
            self.pointcloud.handle,
            utilities.to_rdb_string(filename)
        )

    def import_from_database(self, filename):
        """
        Import changelog from database

        This function imports the entire changelog from an other database.
        This is intended for applications where a database is to be replaced
        by a new one (often derived from the old one) and the processing
        history is to be retained.

        Since 2.3.0
        """
        library.handle.rdb_pointcloud_changelog_import_from_database(
            self.context.handle,
            self.pointcloud.handle,
            utilities.to_rdb_string(filename)
        )
