"""Recipe "create-document": upload a file and create a single-file document from it.

Usage: python recipes/create_document.py [--keep]

With --keep the document stays in the vault; otherwise it is deleted at the end.
"""

import sys
from datetime import datetime, timezone
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from mfiles_client import run  # noqa: E402
from mfiles_values import boolean, lookup, named_acl, property_value, text  # noqa: E402
from recipe_helpers import TEST_PREFIX, connect, delete, describe, keep  # noqa: E402

from mfiles import IRPCObjectOperations_pb2 as ops  # noqa: E402
from mfiles import IRPCObjectOperations_pb2_grpc  # noqa: E402
from mfiles import enums_pb2 as enums  # noqa: E402
from mfiles import structs_pb2 as structs  # noqa: E402

# Bytes per UploadTempFile call: a multiple of 4096, well below the message limit.
BLOCK_SIZE = 4 * 1024 * 1024


def main() -> None:
    with connect() as client:
        title = f"{TEST_PREFIX} Created by the Python sample " \
                f"{datetime.now(timezone.utc):%Y-%m-%d %H:%M:%S}"
        content = f"{title}\r\nHello from the M-Files gRPC API.\r\n".encode("utf-8")
        objects = client.stub(IRPCObjectOperations_pb2_grpc.IRPCObjectOperationsStub)

        # [START upload-file]
        # Upload the content to a temporary file on the server, in blocks. The first call
        # (upload_id 0) starts the upload; the next ones continue it.
        upload_id = 0
        for offset in range(0, max(len(content), 1), BLOCK_SIZE):
            upload_id = objects.UploadTempFile(ops.UploadTempFileRequest(
                upload_id=upload_id,
                total_size_in_bytes=len(content),
                offset=offset,
                data=content[offset:offset + BLOCK_SIZE])).upload_id
        objects.UploadTempFileCommit(ops.UploadTempFileCommitRequest(
            upload_id=upload_id, logical_size=len(content)))
        # [END upload-file]

        # [START create-document]
        response = objects.AddObjectWithFiles(ops.AddObjectWithFilesRequest(
            object_type_id=0,  # Document
            properties=[
                property_value(0, text(title)),      # Name or title
                property_value(100, lookup(1, 1)),   # Class: value list 1, item 1 "Other Document"
                property_value(22, boolean(True)),   # Single file
            ],
            # Always send an ACL: without one, the new document has no permissions and not even
            # its creator can see it. Named ACL -1 is "Full control for all internal users".
            acl=named_acl(-1),
            files=structs.ObjFileSource(
                type=enums.OBJ_FILE_SOURCE_TYPE_UPLOADED_FILE,
                data=structs.ObjFileSourceUnion(
                    uploaded_file=structs.ObjFileSourceUnion.UploadedFileData(
                        upload_id=upload_id,
                        title=title,  # a single-file document's file takes the document's title
                        extension="txt",
                        size=len(content)))),
            check_in=True))
        created = response.created_object.object_version
        print(f"Created {describe(created)}")
        # [END create-document]

        for file in created.version_info.files:
            print(f"  File: {file.title}.{file.extension}, {file.size} bytes")

        if not keep():
            delete(client, created.object_info.obj_id)


if __name__ == "__main__":
    run(main)
