<reponame>thejoltjoker/jdit
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
app.py
Description of app.py.
"""
# TODO copy and verify dailies across disks
# TODO verify files across disks, length + size + hash
# TODO copy sound report and rename it
# TODO rename reports from silverstack
# TODO rename dailies
# TODO send reports as email
# TODO create mhl for offline files
# TODO custom day number by using -d or --day
# TODO custom camera by using -c or --camera
import argparse
import sys
import os
import json
import time
import logging
import hashlib


class JWrangler(object):
    def __init__(self, folder_name, create_folders=True):
        self.logger = self.setup_logger()
        self.settings = self.load_settings()
        self.date = self.get_date()
        self.work_folder = folder_name

        # Print settings to log
        self.logger.info(self.settings)

        if folder_name is not None:
            self.root_folder = folder_name
        else:
            self.root_folder = folder_name

        # Make list of connected drives
        self.active_drives = self.get_active_drives()
        self.logger.debug("self.active_drives = %s", self.active_drives)

    def nefolder_name(self):
        # Check for date folder
        for drive in self.active_drives:
            root_path = self.find_root_folder(drive)
            latest_work_folder = self.get_latest_work_folder(root_path)
            self.logger.debug("latest_work_folder = %s", latest_work_folder)

            # Use the latest folder if it has today's date
            if self.is_work_folder_from_today(latest_work_folder):
                work_folder = latest_work_folder
                self.logger.info("Using work folder %s with today's date on drive %s", self.work_folder, drive)

            # Else create folder with latest day number and today's date
            else:
                new_day_number = self.increment_day_number(latest_work_folder)
                self.logger.debug("new_day_number = %s", new_day_number)
                work_folder = self.settings['structure']['name'].format(day_number=new_day_number, date=self.date)
                self.logger.warning("There's no work folder on %s with today's date", drive)

                # while "invalid answer":
                #     reply = str(input(
                #         "Do you want to create a folder with the name {}? ".format(self.work_folder))).lower().strip()
                #     if reply[:1] in ['y', 'yes']:
                #         print("YES")
                #         self.create_folder_structure(root_path, date=self.date, day_number=new_day_number)
                #         break
                #     if reply[:1] in ['n', 'no']:
                #         print("NO")
                #         break

            self.logger.debug("work_folder = %s", work_folder)
            return work_folder

    def increment_day_number(self, work_folder):
        """Extracts the day number at the end of work folder and increments it"""
        work_folder_split = work_folder.split('_')
        new_day_number = int(work_folder_split[-1]) + 1
        return "{:02d}".format(new_day_number)

    def is_work_folder_from_today(self, work_folder):
        """Returns True if work folder has today's date in it"""
        date = self.get_date()
        if date in work_folder:
            return True
        else:
            return False

    @staticmethod
    def setup_logger():
        """Creates a logger"""
        logger = logging.getLogger()
        handler = logging.StreamHandler()
        formatter = logging.Formatter(
            '%(asctime)s %(name)-12s %(levelname)-8s %(message)s', "%Y-%m-%d %H:%M:%S")
        handler.setFormatter(formatter)
        logger.addHandler(handler)
        logger.setLevel(logging.DEBUG)

        return logger

    @staticmethod
    def load_settings():
        """Load JDIT settings from file"""
        settings_file = os.path.join(os.path.dirname(
            os.path.abspath(__file__)), 'settings.json')

        with open(settings_file, 'r') as read_file:
            settings = json.load(read_file)

        return settings

    def get_active_drives(self):
        """Returns a list of active drives from the list of drives"""
        active_drives = []
        for d in self.settings['drives']:
            # Check if drive is mounted in /Volumes
            drive_path = os.path.abspath(os.path.join('/Users/thejoltjoker/Dropbox/DIT/TEST/Volumes', d))
            # drive_path = os.path.abspath(os.path.join('/Volumes', d))
            self.logger.debug(drive_path)
            if os.path.isdir(drive_path):
                active_drives.append(drive_path)
        self.logger.info("%s of %s drives active", len(active_drives), len(self.settings['drives']))
        return active_drives

    def find_root_folder(self, drive_path):
        """Checks for the project root folder on the given drive"""
        drive = os.path.basename(drive_path)
        root_folder = self.settings['project_name']
        root_path = os.path.join(drive_path, root_folder)
        self.logger.debug("root_path = %s", root_path)
        if os.path.isdir(root_path):
            return root_path
        else:
            self.logger.info("No root folder found on %s with the name %s", drive, root_folder)

    def get_latest_work_folder(self, path):
        """Returns the folder with the highest number"""
        existing_folders = os.listdir(path)
        return max(existing_folders)

    def create_folder_structure(self, path, date=None, day_number=None):
        # Load structure from settings
        structure = self.settings['structure']
        self.logger.debug(structure)

        # Check for existing folders
        existing_folders = os.listdir(path)

        # Get the latest day number and increment for the new one
        if date is None:
            date = self.get_date()

        # Check if todays' date already exists in a folder name
        if [x for x in existing_folders if date in x]:
            self.logger.debug("Folder with today's date exists %s", [x for x in existing_folders if date in x])

        else:
            latest_day_number = max([x.split('_')[2] for x in existing_folders if len(x.split('_')) == 3])
            if day_number is None:
                day_number = "{:02d}".format(int(latest_day_number) + 1)

            self.logger.debug("latest_day_number: %s", latest_day_number)
            self.logger.debug("new_day_number: %s", day_number)

            self.process_folder_structure(structure, path, date, day_number)

    def process_folder_structure(self, node, path, date, day_number):
        path = os.path.join(path, node["name"])
        if 'root' in node:
            path = path.format(day_number=day_number, date=date)

        if 'camera' in node:
            path = path.format(camera='A')

        if not os.path.exists(path):
            os.mkdir(path)

        for child in node.get("children", []):
            self.process_folder_structure(child, path, date, day_number)

    @staticmethod
    def get_date():
        date_format = JWrangler.load_settings()['date_format']
        today = time.strftime(date_format)
        return today

    def get_file_checksum(self, file_path):
        hash_md5 = hashlib.md5()
        with open(file_path, "rb") as f:
            for chunk in iter(lambda: f.read(4096), b""):
                hash_md5.update(chunk)
        return hash_md5.hexdigest()

    def get_file_info(self, file_path):
        file_info = {}
        file_info['name'] = os.path.basename(file_path)
        file_info['path'] = file_path
        file_info['checksum'] = self.get_file_checksum(file_path)
        file_info['size'] = os.path.getsize(file_path)
        file_info['duration'] = os.path.getsize(file_path)

        return file_info

    def get_file_list(self, input_folders):
        base_folders = []
        if type(input_folders) == list:
            base_folders.extend(input_folders)
        else:
            base_folders.append(input_folders)
        file_list = {}
        file_id = 1

        # Go through all folders
        for path in base_folders:
            for subdir, dirs, files in os.walk(path):
                for n, file in enumerate(files):
                    file_path = os.path.join(subdir, file)

                    try:
                        file_info = self.get_file_info(file_path)
                        file_list[file_id] = file_info
                    except Exception as e:
                        print("Error: {}".format(e))
                        pass

                    print("\r{} files found".format(file_id), end='')

                    # Increase id counter
                    file_id += 1
        print('\n')

        return file_list


def main():
    """docstring for main"""
    lm = JWrangler('{date}_DAY_{dayno}'.format(date=JWrangler.get_date(), dayno='21'))


if __name__ == '__main__':
    main()
