# Copyright (c) VOLVICON.
#
# This file is provided solely for educational purposes in connection with
# the Volvicon software and related documentation.
#
# You may use and modify this file for personal or internal purposes when
# working with Volvicon products. Any reproduction, distribution, or use
# of this file outside the Volvicon ecosystem is strictly prohibited
# without prior written authorization from VOLVICON.

"""
Object Management Tutorial.

This tutorial is a complete reference for the Application-level ("app.")
operations that manage objects in a project. Volumes, masks, surfaces,
volume meshes, measurements, and primitives share the same core management
actions: listing, activating, showing/hiding, isolating, renaming,
duplicating, and deleting. Analyses support the same object-management
actions through the corresponding analysis methods.

It also covers session information, mask 3D previews, snapshots, undo/redo,
user messages, and the accessors that return each operations group.

Prerequisites:
- Volvicon application must be running
- A project with some objects loaded makes the listing output more useful

Quick tips (general):
- Instantiate the Application: app = api.Application()
- Names are the handles: every operation refers to objects by their name.
- Each object type has the same family of methods, e.g. rename_volume,
  rename_mask, rename_surface, rename_volume_mesh, rename_measurement,
  rename_primitive, and rename_analysis.
- Text annotations are measurement objects, so manage them with the
  measurement methods (e.g. app.rename_measurement).
- Destructive calls (delete, delete_all, close_project) are commented out so
  running this tutorial does not modify your project.
- All API calls require positional arguments; keyword arguments are not supported.
"""

import ScriptingApi as api

# Create the Application instance — the entry point for every operation.
app = api.Application()

# =============================================================================
# Session Information
# =============================================================================
#: Read details about the running application and the currently open project.
print("Version:", app.get_version())
print("Working directory:", app.get_working_directory())
print("Project file path:", app.get_project_file_path())

# =============================================================================
# Listing Objects by Type
# =============================================================================
#: List the names of every object in the project, grouped by type. Each type
#: exposes its own get-all-names accessor.
all_volumes = app.get_all_volume_names()
all_masks = app.get_all_mask_names()
all_surfaces = app.get_all_surface_names()
all_volume_meshes = app.get_all_volume_mesh_names()
all_measurements = app.get_all_measurement_names()
all_primitives = app.get_all_primitive_names()
all_analyses = app.get_all_analysis_names()

print("Volumes:", all_volumes)
print("Masks:", all_masks)
print("Surfaces:", all_surfaces)
print("Volume meshes:", all_volume_meshes)
print("Measurements:", all_measurements)
print("Primitives:", all_primitives)
print("Analyses:", all_analyses)

# =============================================================================
# Visible Objects by Type
# =============================================================================
#: List only the objects of each type that are currently shown in the views.
print("Visible volumes:", app.get_visible_volume_names())
print("Visible masks:", app.get_visible_mask_names())
print("Visible surfaces:", app.get_visible_surface_names())
print("Visible volume meshes:", app.get_visible_volume_mesh_names())
print("Visible measurements:", app.get_visible_measurement_names())
print("Visible primitives:", app.get_visible_primitive_names())
print("Visible analyses:", app.get_visible_analysis_names())

# =============================================================================
# Active Objects
# =============================================================================
#: Read and set the active object of each type. The active object is the single
#: target used by operations that act on the active volume, mask, surface, and
#: so on. Each type has its own active getter and setter, for example
#: get_active_volume_name and set_active_volume.
print("Active volume:", app.get_active_volume_name())
print("Active mask:", app.get_active_mask_name())
print("Active surface:", app.get_active_surface_name())
print("Active volume mesh:", app.get_active_volume_mesh_name())
print("Active measurement:", app.get_active_measurement_name())
print("Active primitive:", app.get_active_primitive_name())
print("Active analysis:", app.get_active_analysis_name())

if all_volumes:
    app.set_active_volume(all_volumes[0])
if all_masks:
    app.set_active_mask(all_masks[0])
if all_surfaces:
    app.set_active_surface(all_surfaces[0])
if all_volume_meshes:
    app.set_active_volume_mesh(all_volume_meshes[0])
if all_measurements:
    app.set_active_measurement(all_measurements[0])
if all_primitives:
    app.set_active_primitive(all_primitives[0])
if all_analyses:
    app.set_active_analysis(all_analyses[0])

# =============================================================================
# Visibility - Show and Hide
# =============================================================================
#: Show or hide objects by passing their names together with a True or False flag.
if all_volumes:
    app.set_volumes_visible(all_volumes, True)
if all_masks:
    app.set_masks_visible(all_masks, True)
if all_surfaces:
    app.set_surfaces_visible(all_surfaces, True)
if all_volume_meshes:
    app.set_volume_meshes_visible(all_volume_meshes, True)
if all_measurements:
    app.set_measurements_visible(all_measurements, True)
if all_primitives:
    app.set_primitives_visible(all_primitives, True)
if all_analyses:
    app.set_analyses_visible(all_analyses, True)

# =============================================================================
# Visibility - Isolate
# =============================================================================
#: Show only the listed objects of a type and hide the rest. Passing an empty
#: list shows all objects of that type again. Isolation is available for
#: volumes, masks, surfaces, volume meshes, measurements, primitives, and
#: analyses.
if all_surfaces:
    app.isolate_surfaces([all_surfaces[0]])   # show only the first surface
    app.isolate_surfaces([])                  # show all surfaces again

if all_analyses:
    app.isolate_analyses([all_analyses[0]])  # show only the first analysis
    app.isolate_analyses([])                 # show all analyses again

# The same pattern is available for these object types:
# app.isolate_volumes([...])
# app.isolate_masks([...])
# app.isolate_volume_meshes([...])
# app.isolate_measurements([...])
# app.isolate_primitives([...])
# app.isolate_analyses([...])

# =============================================================================
# Renaming Objects
# =============================================================================
#: Rename any object using the rename method for its type. A text annotation is
#: a measurement object, so it is renamed with rename_measurement.
# app.rename_volume("Volume_1", "CT_Scan")
# app.rename_mask("Mask_1", "Bone")
# app.rename_surface("Surface_1", "Femur")
# app.rename_volume_mesh("VolumeMesh_1", "Femur_Mesh")
# app.rename_measurement("Text Annotation 1", "Tumor label")
# app.rename_primitive("Sphere 001", "Marker")
# app.rename_analysis("WallThickness_1", "Inspection")

# =============================================================================
# Duplicating Objects
# =============================================================================
#: Copy objects of any type. Each duplicate method returns the names of the
#: created copies.
# duplicated = app.duplicate_volumes(["Volume_1"])
# duplicated = app.duplicate_masks(["Mask_1"])
# duplicated = app.duplicate_surfaces(["Surface_1"])
# duplicated = app.duplicate_volume_meshes(["VolumeMesh_1"])
# duplicated = app.duplicate_measurements(["Distance 1"])
# duplicated = app.duplicate_primitives(["Sphere 001"])
# duplicated = app.duplicate_analyses(["WallThickness_1"])

# =============================================================================
# Deleting Objects
# =============================================================================
#: Remove specific objects, or clear every object of a type. delete_all methods
#: take a flag; pass False to skip the confirmation dialog. These operations are
#: destructive and are not easily undone.
# app.delete_volumes(["Volume_to_delete"])
# app.delete_all_volumes(False)
# app.delete_masks(["Mask_to_delete"])
# app.delete_all_masks(False)
# app.delete_surfaces(["Surface_to_delete"])
# app.delete_all_surfaces(False)
# app.delete_volume_meshes(["VolumeMesh_to_delete"])
# app.delete_all_volume_meshes(False)
# app.delete_measurements(["Measurement_to_delete"])
# app.delete_all_measurements(False)
# app.delete_primitives(["Primitive_to_delete"])
# app.delete_all_primitives(False)
# app.delete_analyses(["Analysis_to_delete"])
# app.delete_all_analyses(False)

# =============================================================================
# Mask 3D Preview
# =============================================================================
#: Control the 3D surface preview of masks: set its quality, generate it for the
#: visible masks, and remove it. Available quality levels are Low, Medium, High,
#: and Optimal.
app.set_mask_3d_preview_quality(api.Mask3dPreviewQuality.Optimal)
print("Mask 3D preview quality:", app.get_mask_3d_preview_quality())

if all_masks:
    # Generate previews for the currently visible masks.
    app.generate_mask_3d_preview(app.get_visible_mask_names())

    # Remove the preview of specific masks, or of all masks.
    # app.remove_mask_3d_preview([all_masks[0]])
    # app.remove_all_mask_3d_previews()

# =============================================================================
# Snapshots
# =============================================================================
#: Capture the current view as an image file on disk, or as in-memory image data.
# app.save_snapshot_to_disk(api.SnapshotType.View3D, "C:/output/view3d.png", "PNG")

# image : api.Image2D = app.grab_snapshot(api.SnapshotType.View3D)
# print("Snapshot size:", image.width, "x", image.height, "format:", image.format)
# # image.data holds the raw image bytes

# =============================================================================
# Undo and Redo
# =============================================================================
#: Step the application backward or forward through recent actions.
# app.undo()
# app.redo()

# =============================================================================
# User Messages
# =============================================================================
#: Show information, warning, or question dialogs to the user.
# app.show_message_box("Processing finished.", "Information")
# app.show_message_box("Low memory.", "Warning", api.MsgBoxLevel.Warn)
# proceed = app.show_question_message_box("Continue?", "Confirm")

# =============================================================================
# Project Management
# =============================================================================
#: Open, save, and close project files.
# app.open_project("C:/data/project.vvcx")
# app.save_project()                              # save to the current location
# app.save_project("C:/data/project_copy.vvcx")  # save to a new location
# app.close_project()

# =============================================================================
# Operations Group Accessors
# =============================================================================
#: Obtain each specialized operations group from the Application. Object render
#: properties come from these groups, for example
#: surface_operations.get_render_properties_operations(), never from app directly.
volume_operations = app.get_volume_operations()
mask_operations = app.get_mask_operations()
surface_operations = app.get_surface_operations()
volume_mesh_operations = app.get_volume_mesh_operations()
fem_operations = app.get_fem_operations()
measurement_operations = app.get_measurement_operations()
primitive_operations = app.get_primitive_operations()
registration_operations = app.get_registration_operations()
analysis_operations = app.get_analysis_operations()
measure_operations = app.get_measure_operations()
ai_segmentation = app.get_ai_segmentation()
view_operations = app.get_view_operations()
preferences_operations = app.get_preferences_operations()

print("Object management tutorial completed successfully.")

