#!/usr/bin/env python3

# Copyright (C) 2023 Julian Mutter (julian.mutter@comumail.de)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

import os
import subprocess
from dotenv import load_dotenv

load_dotenv()

DESTINATION_FOLDER = os.environ["TRANSFER_DESTINATION_FOLDER"]

RIPPED_DIR = "ripped"


def main():
    chdir_to_script_dir()

    for dvd_type in ("movie", "series"):
        for dvd in list_ripped_dvds(dvd_type):
            print(f"Transferring {dvd_type}: {dvd}")
            success = transfer_ripped_dvd_to_transcoder(dvd, dvd_type)
            print()
            if not success:
                print("Transfer failed!")
                exit(1)

    print("Success")


def chdir_to_script_dir():
    os.chdir(os.path.dirname(__file__))


def list_ripped_dvds(dvd_type):
    path = os.path.join(RIPPED_DIR, dvd_type)
    try:
        dvd_titles = os.listdir(path)
        dvd_titles = filter(lambda title: not title.endswith(".lock"), dvd_titles)
        return map(lambda dvd_title: os.path.join(path, dvd_title), dvd_titles)
    except FileNotFoundError:
        print(
            f"Directory {path} not found. Running the ripper script will generate it."
        )
        exit(1)


def transfer_ripped_dvd_to_transcoder(ripped_dvd, dvd_type) -> bool:
    """Returns: success of command"""

    dvd_title = os.path.basename(ripped_dvd)

    local_folder = os.path.dirname(ripped_dvd)
    remote_folder = os.path.join(DESTINATION_FOLDER, dvd_type)

    lock_file_name = dvd_title + ".lock"
    lock_file_local = os.path.join(local_folder, lock_file_name)
    lock_file_remote = os.path.join(remote_folder, lock_file_name)

    try:
        create_local_lock_file(lock_file_local)
        transfer_lock_file(lock_file_local, lock_file_remote)

        transfer_ripped_dvd(ripped_dvd, remote_folder)
        remove_empty_dirs_lefover_from_rsync(local_folder)

        delete_local_lock_file(lock_file_local)
        remove_remote_lock_file(lock_file_name, local_folder, remote_folder)

    except subprocess.CalledProcessError:
        return False

    return True


def create_local_lock_file(path):
    create_empty_file(path)


def create_empty_file(path):
    with open(path, "w") as _:
        pass


def delete_local_lock_file(path):
    os.remove(path)


def transfer_lock_file(lock_file_local, lock_file_remote):
    subprocess.run(["rsync", "-e ssh", lock_file_local, lock_file_remote], check=True)


def transfer_ripped_dvd(ripped_dvd, destination_folder):
    subprocess.run(
        [
            "rsync",
            "-az",
            "-e ssh",
            "--remove-source-files",
            ripped_dvd,
            destination_folder,
        ],
        check=True,
    )


def remove_empty_dirs_lefover_from_rsync(folder):
    """Rsyncs --remove-source-files does not delete directories, so call this method to fix this"""
    subprocess.run(
        ["find", folder, "-depth", "-type", "d", "-empty", "-delete"],
        check=True,
    )


def remove_remote_lock_file(lock_file_name, folder, destination_folder):
    subprocess.run(
        [
            "rsync",
            "-r",
            "-e ssh",
            "--delete",
            f"--include={lock_file_name}",
            "--exclude=*",
            folder + "/",
            destination_folder + "/",
        ],
        check=True,
    )


if __name__ == "__main__":
    main()