
import logging
import subprocess

from enum import Enum


class NTFSImplementation(Enum):
    KERNEL = 1
    NTFS3G = 2


class NTFSLibrary:
    """
    A library for managing NTFS filesystems.

    Attributes:
        logger (logging.Logger): Logger for the class.
        implementation (NTFSImplementation): The implementation to use for mounting NTFS filesystems.
    """

    def __init__(self, implementation):
        """
        Initializes the instance with the given implementation.

        Args:
            implementation: The implementation to be used by the instance.

        Attributes:
            logger (logging.Logger): Logger instance for the class, set to debug level.
            implementation: The implementation provided during initialization.
        """
        self.logger = logging.getLogger("NTFSLibrary")
        self.logger.setLevel(logging.DEBUG)
        self.implementation = implementation

        self.logger.debug("Initializing")

    def create_filesystem(self, device, label):
        """
        Creates an NTFS filesystem on the specified device with the given label.

        Args:
            device (str): The device path where the NTFS filesystem will be created.
            label (str): The label to assign to the NTFS filesystem.

        Returns:
            None

        Logs:
            Logs the creation process with the device and label information.
        """
        self.logger.info(f"Creating NTFS in {device} with label {label}")

        subprocess.run(["/usr/sbin/mkntfs", device, "-Q", "-L", label], check=True)


    def mount_filesystem(self, device, mountpoint):
        """
        Mounts a filesystem on the specified mountpoint using the specified NTFS implementation.

        Args:
            device (str): The device path to be mounted (e.g., '/dev/sda1').
            mountpoint (str): The directory where the device will be mounted.

        Raises:
            ValueError: If the NTFS implementation is unknown.

        """
        self.logger.info(f"Mounting {device} in {mountpoint} using implementation {self.implementation}")
        if self.implementation == NTFSImplementation.KERNEL:
            subprocess.run(["/usr/bin/mount", "-t", "ntfs3", device, mountpoint], check = True)
        elif self.implementation == NTFSImplementation.NTFS3G:
            subprocess.run(["/usr/bin/ntfs-3g", device, mountpoint], check = True)
        else:
            raise ValueError("Unknown NTFS implementation: {self.implementation}")

    def modify_uuid(self, device, uuid):
        """
        Modify the UUID of an NTFS device.

        This function changes the UUID of the specified NTFS device to the given UUID.
        It reads the current UUID from the device, logs the change, and writes the new UUID.

        Args:
            device (str): The path to the NTFS device file.
            uuid (str): The new UUID to be set, in hexadecimal string format.

        Raises:
            IOError: If there is an error opening or writing to the device file.
        """

        ntfs_uuid_offset = 0x48
        ntfs_uuid_length = 8

        binary_uuid = bytearray.fromhex(uuid)
        binary_uuid.reverse()

        self.logger.info(f"Changing UUID on {device} to {uuid}")
        with open(device, 'r+b') as ntfs_dev:
            self.logger.debug("Reading %i bytes from offset %i", ntfs_uuid_length, ntfs_uuid_offset)

            ntfs_dev.seek(ntfs_uuid_offset)
            prev_uuid = bytearray(ntfs_dev.read(ntfs_uuid_length))
            prev_uuid.reverse()
            prev_uuid_hex = bytearray.hex(prev_uuid)
            self.logger.debug(f"Previous UUID: {prev_uuid_hex}")

            self.logger.debug("Writing...")
            ntfs_dev.seek(ntfs_uuid_offset)
            ntfs_dev.write(binary_uuid)
