import datetime
import logging
import os

import misc
from registry import Registry

class Migrator:
    def __init__(self, src_dir, dst_dir, reg_db=None):
        self._base_src_dir = src_dir
        self._base_dst_dir = dst_dir
        self._reg = Registry(reg_db)

    def migrate(self, remove):
        for src_file_name, src_file_path in misc.walk_media_files(self._base_src_dir):
            logging.debug('Migrating %s...', src_file_name)
            try:
                if not self._reg.is_registered(src_file_path):
                    self._migrate_single(src_file_name, src_file_path, remove)
                    self._reg.register(src_file_path)
                else:
                    self._reg.refresh(src_file_path)
            except Exception as e:
                logging.error('Error migrating %s: %s', src_file_path, str(e))
        self._reg.clean()

    def _migrate_single(self, src_file_name, src_file_path, remove):
        meta_time = misc.extract_meta_time(src_file_path)

        if meta_time:
            dst_sub_dir = datetime.datetime.fromtimestamp(meta_time).strftime("%Y/%m")
        else:
            dst_sub_dir = "na"

        dst_dir = os.path.join(self._base_dst_dir, dst_sub_dir)
        dst_file_path = os.path.join(dst_dir, src_file_name)

        if not os.path.exists(dst_file_path):
            alt_dst_dir = misc.find_alt_file(self._base_dst_dir,
                                             src_file_name,
                                             os.path.getsize(src_file_path),
                                             meta_time,
                                             exclude_dir=self._base_src_dir)
            if alt_dst_dir:
                dst_dir = alt_dst_dir
                dst_file_path = os.path.join(dst_dir, src_file_name)

        if not os.path.exists(dst_file_path):
            if not os.path.exists(dst_dir):
                os.makedirs(dst_dir)
            misc.import_file(src_file_path, dst_file_path)
        else:
            src_time = os.path.getmtime(src_file_path)
            dst_time = os.path.getmtime(dst_file_path)
            if src_time > dst_time:
                misc.import_file(src_file_path, dst_file_path)

        if remove:
            os.remove(src_file_path)

    def cleanup(self):
        for root, dirs, files in os.walk(self._base_src_dir, topdown=False):
            for name in files:
                full_path = os.path.join(root, name)
                if not misc.is_media_file(full_path):
                    try:
                        os.remove(full_path)
                    except Exception as e:
                        logging.warn('Error cleaning file %s: %s', full_path, str(e))
            for name in dirs:
                full_path = os.path.join(root, name)
                try:
                    os.rmdir(full_path)
                except Exception as e:
                    logging.warn('Error cleaning dir %s: %s', full_path, str(e))
