# -*- Mode: Python -*-

import argparse
import exifread
import os
import re
import sys
import time

W = sys.stderr.write
PJ = os.path.join

target_root = '/Users/rushing/Pictures/alpha'
exif_date_keys = ['EXIF DateTimeOriginal', 'Image DateTime']
exif_time_re = re.compile (
    '([0-9]{2,4}):([0-9]{2,2}):([0-9]{2,2}) ' # YMD
    '([0-9]{2,2}):([0-9]{2,2}):([0-9]{2,2})'  # HMS
)
raw_exts = {'.ARW', '.RAW'}
jpg_exts = {'.JPG', '.HEIC'}
vid_exts = {'.MP4', '.MOV'}

all_copied_files = []

class SizeConflict (Exception):
    pass
class SizeMismatch (Exception):
    pass
class DateParseError (Exception):
    pass

def israw (path):
    base, ext = os.path.splitext (path)
    return ext in raw_exts

def get_date_size (img):
    st = os.stat (img)
    t = time.localtime (st.st_mtime)
    y, m, d = t.tm_year, t.tm_mon, t.tm_mday
    return (y, m, d), st.st_size

def get_file_date (path):
    return get_date_size(path)[0]

def get_file_size (path):
    return get_date_size(path)[1]

def parse_exif_date (date):
    # 1999:04:12 14:06:40
    m = exif_time_re.match (date)
    if m is None:
        raise DateParseError (date)
    else:
        return tuple(int(x) for x in m.groups()[:3])

def get_img_date (path):
    tags = exifread.process_file (open (path, 'rb'), details=False)
    if not tags:
        return None
    else:
        for key in exif_date_keys:
            if tags.has_key (key):
                tag = str (tags[key])
                if tag == "0000:00:00 00:00:00":
                    continue
                else:
                    return parse_exif_date (tag)
        return None

def maybe_make (y, m, d):
    yp = PJ (target_root, '%4d' % y)
    if not os.path.isdir (yp):
        W ('creating %s\n' % (yp,))
        os.mkdir (yp)
    dp = PJ (yp, '%02d_%02d' % (m, d))
    if not os.path.isdir (dp):
        W ('creating %s\n' % (dp,))
        os.mkdir (dp)
        os.mkdir (PJ (dp, 'raw'))
        return dp, False
    else:
        return dp, True

def copy_file (src, dst, size):
    W ('copying: %s %s\n' % (src, dst))
    os.system ('/bin/cp -a "%s" "%s"' % (src, dst))
    _, size0 = get_date_size (dst)
    if size != size0:
        raise SizeMismatch (src, dst)
    else:
        all_copied_files.append (src)

# is this file already present at the target?
def maybe_copy (src_path):
    ymd = get_img_date (src_path)
    if ymd is not None:
        y, m, d = ymd
        size = get_file_size (src_path)
        base, name = os.path.split (src_path)
        day_path, present = maybe_make (y, m, d)
        if israw (name):
            dst_path = PJ (day_path, 'raw', name)
        else:
            dst_path = PJ (day_path, name)
        if os.path.isfile (dst_path):
            size0 = get_file_size (dst_path)
            if size0 != size:
                raise SizeConflict (src_path, dst_path)
            else:
                W ('already: %s %s\n' % (src_path, dst_path))
        else:
            copy_file (src_path, dst_path, size)

if __name__ == '__main__':
    import sys
    for path in sys.argv[1:]:
        maybe_copy (path)
    for path in all_copied_files:
        os.unlink (path)

