#!/usr/bin/env python3

import os
import subprocess
import shutil
from datetime import datetime

TMP_DIR = "tmp"
RAW_DIR = "raw"
TRANSCODED_DIR = "transcoded"
LOGFILE = "transcode.log"

HANDBRAKE_PRESET = "General/HQ 1080p30 Surround"
HANDBRAKE_AUDIO_LANG_LIST = "de,en"
OUT_VIDEO_FORMAT = ".m4v"
MIN_EPISODES_DURATION_SECONDS = 10 * 60


def main():
    chdir_to_script_dir()
    mkdirs()
    for dvd_type in ("movie", "series"):
        for dvd in filter(is_dvd_files_not_locked, list_ripped_dvds(dvd_type)):
            print(f"Transcoding {dvd_type} {dvd}")
            # TOOD: nice transcoding process so it does not block server
            success = transcode_ripped_dvd(dvd, dvd_type)
            dvd_title = os.path.basename(dvd)
            if success:
                mv_video_from_tmp_to_transcoded_dir(dvd_title, dvd_type)
                write_to_logfile(dvd_type, dvd_title, "Success")
                delete_original_video_files(dvd)
                delete_transcoding_logfile(dvd)
                print("Success")
            else:
                write_to_logfile(dvd_type, dvd_title, "FAILURE")
                err_log_file = dvd + ".err.log"
                print(f"Failed. Please see logs at {err_log_file}")

    delete_tmp_dir()


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


def mkdirs():
    os.makedirs(TMP_DIR, exist_ok=True)
    os.makedirs(TRANSCODED_DIR, exist_ok=True)
    os.makedirs(RAW_DIR, exist_ok=True)
    os.makedirs(os.path.join(RAW_DIR, "movie"), exist_ok=True)
    os.makedirs(os.path.join(RAW_DIR, "series"), exist_ok=True)


def list_ripped_dvds(dvd_type):
    path = os.path.join(RAW_DIR, dvd_type)
    try:
        dvd_titles = os.listdir(path)
        dvd_titles = filter(lambda title: not title.endswith(".lock"), dvd_titles)
        dvd_titles = filter(lambda title: not title.endswith(".err.log"), dvd_titles)
        dvd_titles = filter(lambda title: not title.endswith(".log"), 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 is_dvd_files_not_locked(dvd):
    return not os.path.exists(dvd + ".lock") and not os.path.exists(dvd + ".err.log")


def transcode_ripped_dvd(ripped_dvd, dvd_type):
    if dvd_type == "movie":
        return transcode_movie(ripped_dvd)
    else:
        return transcode_series(ripped_dvd)


def transcode_movie(movie):
    video_file_name = os.path.basename(movie) + OUT_VIDEO_FORMAT
    output_file = os.path.join(TMP_DIR, video_file_name)
    log_file_path = movie + ".log"

    with open(log_file_path, "w") as log_file:

        proc = subprocess.run(
            [
                "HandBrakeCLI",
                "--preset",
                HANDBRAKE_PRESET,
                "--main-feature",
                "--first-audio",
                "--audio-lang-list",
                HANDBRAKE_AUDIO_LANG_LIST,
                "--input",
                movie,
                "--output",
                output_file,
            ],
            stderr=subprocess.STDOUT,
            stdout=log_file,
        )
    return proc.returncode == 0


def transcode_series(series):
    # --min-duration MIN_EPISODES_DURATION
    # --title 1
    # --title 2
    # etc
    pass


def mv_video_from_tmp_to_transcoded_dir(video_title, video_type):
    src = os.path.join(TMP_DIR, video_title)
    dst = os.path.join(TRANSCODED_DIR, video_type, video_title)

    shutil.move(src, dst)


def write_to_logfile(dvd_type, dvd_title, tag):
    date = datetime.now().strftime("%d.%m.%Y %H:%M:%S")
    log_line = f'{date} - {dvd_type} - "{dvd_title}" - {tag}'

    with open(LOGFILE, "a") as file:
        file.write(log_line + "\n")


def delete_transcoding_logfile(dvd):
    os.remove(dvd + ".log")


def rename_transcoding_logfile_as_error_log(dvd):
    shutil.move(dvd + ".log", dvd + ".err.log")


def delete_original_video_files(folder):
    os.rmdir(folder)


def delete_tmp_dir():
    try:
        os.rmdir(os.path.join(TMP_DIR))
    except FileNotFoundError:
        pass


if __name__ == "__main__":
    main()