"""Generic handler for moving services"""

from __future__ import annotations
import shutil
from typing import List

from selfprivacy_api.jobs import Job, report_progress
from selfprivacy_api.utils.block_devices import BlockDevice
from selfprivacy_api.services.owned_path import Bind


class MoveError(Exception):
    """Move of the data has failed"""


def check_volume(volume: BlockDevice, space_needed: int) -> None:
    # Check if there is enough space on the new volume
    if int(volume.fsavail) < space_needed:
        raise MoveError("Not enough space on the new volume.")

    # Make sure the volume is mounted
    if not volume.is_root() and f"/volumes/{volume.name}" not in volume.mountpoints:
        raise MoveError("Volume is not mounted.")


def check_binds(volume_name: str, binds: List[Bind]) -> None:
    # Make sure current actual directory exists and if its user and group are correct
    for bind in binds:
        bind.validate()


def unbind_folders(owned_folders: List[Bind]) -> None:
    for folder in owned_folders:
        folder.unbind()


# May be moved into Bind
def move_data_to_volume(
    binds: List[Bind],
    new_volume: BlockDevice,
    job: Job,
) -> List[Bind]:
    current_progress = job.progress
    if current_progress is None:
        current_progress = 0

    progress_per_folder = 50 // len(binds)
    for bind in binds:
        old_location = bind.location_at_volume()
        bind.drive = new_volume
        new_location = bind.location_at_volume()

        try:
            shutil.move(old_location, new_location)
        except Exception as error:
            raise MoveError(
                f"could not move {old_location} to {new_location} : {str(error)}"
            ) from error

        progress = current_progress + progress_per_folder
        report_progress(progress, job, "Moving data to new volume...")
    return binds


def ensure_folder_ownership(folders: List[Bind]) -> None:
    for folder in folders:
        folder.ensure_ownership()


def bind_folders(folders: List[Bind]):
    for folder in folders:
        folder.bind()