#!/usr/bin/env nix-shell
#! nix-shell -i python3 --pure
#! nix-shell -p python3 python3Packages.coloredlogs

"""
Same as picture_name_date
except it's tailored for OpenCamera.
It uses filenames, that way:
- Easier to get metadata
- JPG/DNG, MP4/SRT keep the same filename
"""

import argparse
import logging
import os
import re

import coloredlogs

log = logging.getLogger(__name__)
coloredlogs.install(level="DEBUG", fmt="%(levelname)s %(message)s", logger=log)

PATTERNS = [
    re.compile(  # OpenCamera
        r"^(?P<type>IMG|VID)_"
        # No TRIM. We don't want those as they're a short copy of an existing VID.
        r"(?P<Y>\d\d\d\d)(?P<M>\d\d)(?P<D>\d\d)_"
        r"(?P<h>\d\d)(?P<m>\d\d)(?P<s>\d\d)"
        r"(?P<dup>_(\d+))?"
        r"(?P<spec>_(PANO|HDR))?"
        r"\.(?P<ext>jpg|dng|mp4|srt)$"
    ),
    re.compile(  # Samsung camera app (?)
        r"(?P<Y>\d\d\d\d)(?P<M>\d\d)(?P<D>\d\d)_"
        r"(?P<h>\d\d)(?P<m>\d\d)(?P<s>\d\d)"
        r"\.(?P<ext>jpg|mp4)$"
    ),
    re.compile(  # Telegram Media Downloader photo
        r"photo_"
        r"(?P<Y>\d\d\d\d)-(?P<M>\d\d)-(?P<D>\d\d)_"
        r"(?P<h>\d\d)-(?P<m>\d\d)-(?P<s>\d\d)"
        r"(?P<dup>_\d{19})"
        r"\.(?P<ext>jpg)$"
    ),  # Time of publication, not time of photo!
    re.compile(  # Telegram Media Downloader video
        r"video_"
        r"(?P<Y>\d\d\d\d)-(?P<M>\d\d)-(?P<D>\d\d)_"
        r"(?P<h>\d\d)-(?P<m>\d\d)-(?P<s>\d\d)"
        r"(?P<dup>_\d{19})"
        r"\.(?P<ext>mp4)$"
    ),  # Time of publication, not time of video!
]


def main(args: argparse.Namespace) -> None:
    for root, _, files in os.walk(args.dir):
        for filename in files:
            full_path = os.path.join(root, filename)
            for pattern in PATTERNS:
                match = re.match(pattern, filename)
                if match:
                    break
            else:
                log.warning(f"{full_path} doesn't any pattern")
                continue

            # Build new filename
            m = match.groupdict()
            new_filename = (
                f"{m['Y']}-{m['M']}-{m['D']}_"
                f"{m['h']}-{m['m']}-{m['s']}"
                f"{m.get('dup') or ''}"
                f"{m.get('spec') or ''}"
                f"{args.suffix}"
                f".{m['ext']}"
            )
            new_path = os.path.join(args.dir, new_filename)
            # TODO Allow keeping image in same folder

            # Rename file
            if full_path == new_path:
                log.debug(f"{full_path} already at required filename")
                continue
            log.info(f"{full_path} →\t{new_path}")
            if os.path.exists(new_path):
                raise FileExistsError(f"{new_path} already exists!")
            if not args.dry:
                os.rename(full_path, new_path)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description="Rename OpenCamera files based on their dates"
    )
    parser.add_argument(
        "dir",
        metavar="DIRECTORY",
        type=str,
        default=".",
        nargs="?",
        help="Directory containing the pictures",
    )
    parser.add_argument(
        "-d",
        "--dry",
        action="store_true",
        help="Do not actually rename, just show old and new path",
    )
    parser.add_argument(
        "-s",
        "--suffix",
        default="",
        help="Text to add before the extension",
    )
    args = parser.parse_args()
    main(args)