from argparse import ArgumentParser, Namespace
import glob
import shutil
from typing import List
import os
from dataclasses import dataclass
import time


@dataclass
class Arguments:
    source_path: str
    dest_path: str


def dir_path(string) -> str:
    if os.path.isdir(string):
        return string
    else:
        raise NotADirectoryError(string)


def addArguments(parser: ArgumentParser) -> None:
    parser.add_argument('from_path', type=dir_path)
    parser.add_argument('to_path', type=dir_path)
    parser.set_defaults(func=main)


def parseRawArgs(args: Namespace) -> Arguments:
    return Arguments(args.from_path, args.to_path)


def filesByExtension(source_path: str, extension: str) -> List[str]:
    upper_extension = extension.upper()
    lower_extension = extension.lower()

    source_files = []

    source_files.extend(glob.glob(f"**/*.{upper_extension}", root_dir=source_path, recursive=True))
    source_files.extend(glob.glob(f"**/*.{lower_extension}", root_dir=source_path, recursive=True))

    return source_files


def main(raw_args: Namespace) -> None:
    args = parseRawArgs(raw_args)

    jpegs = filesByExtension(args.source_path, "JPG")
    raws = filesByExtension(args.source_path, "RAF")
    movs = filesByExtension(args.source_path, "MOV")

    total_size = 0

    for file in jpegs:
        total_size += os.path.getsize(os.path.join(args.source_path, file))

    for file in raws:
        total_size += os.path.getsize(os.path.join(args.source_path, file))

    for file in movs:
        total_size += os.path.getsize(os.path.join(args.source_path, file))

    block_size = os.statvfs(args.dest_path).f_frsize
    blocks_free = os.statvfs(args.dest_path).f_bfree
    assert(block_size * blocks_free > total_size)

    for (files, subdir) in zip([jpegs, raws, movs], ["JPEG", "RAW", "MOV"]):
        try:
            os.mkdir(os.path.join(args.dest_path, subdir))
        except FileExistsError:
            print("Warning: path exists")
            pass

        time.sleep(1)

        for file in files:
            source_file = os.path.join(args.source_path, file)
            dest_folder = os.path.join(args.dest_path, subdir)
            print(f"Copying {source_file} to {dest_folder}")
            shutil.copy2(source_file, dest_folder)

    
        