#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
#*******************************************************************************
#
#  Copyright 2026 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
#
#*******************************************************************************
#
"""
rdb-example-12-clone-file.py

This example shows how to clone (copy) an existing database.
"""

from typing import Iterable, Optional

from riegl.rdb import *


def rdb_clone(
    source: str,                                 # input file path (must exist)
    target: str,                                 # output file path (is overwritten)
    selection: Optional[str] = None,             # point filter string (None = all)
    attributes: Optional[Iterable[str]] = None,  # point attribute names (None = all)
    chunk_size: int = 100*1000                   # number of points to copy in one step
) -> None:
    ctx = Context()
    with rdb_open(source, context=ctx) as reader:
        # get source file creation settings:
        settings = CreateSettings(ctx)
        settings.load(reader.transactions[1].settings)

        # create target file with the same settings:
        with rdb_create(target, settings, context=ctx) as writer:
            with Transaction(writer, "Clone", "Duplicator 1.0") as transaction:
                # clone all meta data entries:
                for name, value in reader.meta_data.items():
                    if name == RDB_RIEGL_POINT_ATTRIBUTE_GROUPS:
                        continue  # always defined -> skip
                    writer.meta_data[name] = value

                # clone all point attribute definitions:
                attributes = set(attributes or reader.point_attributes)
                attributes.discard(RDB_RIEGL_ID)  # is auto-generated
                for name in attributes:
                    if name == settings.primary_attribute.name:
                        continue  # always defined -> skip
                    writer.point_attributes.add(reader.point_attributes[name])

                # clone all point data:
                buffer = PointBuffer(reader, attributes, chunk_size)
                with reader.select(selection) as select, writer.insert() as insert:
                    select.bind(buffer)  # tell select query where to write data to
                    insert.bind(buffer)  # tell insert query where to read data from
                    while count := select.next(chunk_size):
                        insert.next(count)

                # finally commit transaction:
                transaction.commit()
