#!/usr/bin/env python3
#coding: UTF-8

from argparse import ArgumentParser
import logging
from pathlib import Path
import re
import time

from requests import RequestException
from tfatool import command, sync, info, cgi


logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO, style="{",
                    format="{asctime} | {levelname} | {name} | {message}")
logging.getLogger("requests").setLevel(logging.WARNING)

parser = ArgumentParser()

actions = parser.add_argument_group("Actions")
actions.add_argument("-l", "--list-files", action="store_true")
actions.add_argument("-c", "--count-files", action="store_true")
actions.add_argument("-s", "--sync-forever", action="store_true",
                     help="watch for new files in REMOTE_DIR, copy them to LOCAL_DIR "
                          "(runs until CTRL-C)")
actions.add_argument("-S", "--sync-once", default=False,
                     choices=["time", "name", "all"],
                     help="move files (all or by most recent name/timestamp) from "
                          "REMOTE_DIR to LOCAL_DIR, then quit")

setup = parser.add_argument_group("Setup")
setup.add_argument("-r", "--remote-dir", default=info.DEFAULT_DIR,
                   help="FlashAir directory to work with (default: {})".format(
                        info.DEFAULT_DIR))
setup.add_argument("-d", "--local-dir", default=".",
                   help="local directory to work with (default: working dir)")
setup.add_argument("-j", "--only-jpg", action="store_true",
                   help="filter for only JPEG files")
setup.add_argument("-k", "--match-regex", default=None,
                   help="filter for files that match the given pattern")
setup.add_argument("-n","--n-files", type=int, default=1,
                    help="Number of files to move in --sync-once mode")


def run():
    args = parser.parse_args()
    filters = []
    if args.only_jpg:
        jpg_filter = lambda f: f.filename.lower().endswith("jpg")
        filters.append(jpg_filter)
    if args.match_regex:
        regex_filter = lambda f: re.match(args.match_regex, f.filename)
        filters.append(regex_filter)

    try:
        if args.list_files:
            print_file_list(filters, args)
        if args.count_files:
            print_file_count(filters, args)
    except RequestException as e:
        print("\nHTTP request exception: {}".format(e))

    if args.sync_once == "all" and args.n_files != 1:
        parser.error("`--sync-once all` doesn't make sense with `--num-files N`")

    if args.sync_forever or args.sync_once:
        logger.info("Syncing files from {} to {}".format(
            args.remote_dir, args.local_dir))
        local_path = Path(args.local_dir)
        if not local_path.is_dir():
            logger.info("Creating directory '{}'".format(args.local_dir))
            local_path.mkdir()
        if args.sync_once == "name":
            sync_once(sync.by_name, filters, args)
        elif args.sync_once == "time":
            sync_once(sync.by_time, filters, args)
        elif args.sync_once == "all":
            logger.info("Retreiving ALL matched files")
            files = command.list_files(*filters, remote_dir=args.remote_dir)
            sync.by_files(files, dest=args.local_dir)
        if args.sync_forever:
            try:
                sync_loop(filters, args)
            except KeyboardInterrupt:
                pass


def sync_once(by_method, filters, args):
    logger.info("Retrieving {} latest file(s) by {}".format(
        args.n_files, args.sync_once))
    try:
        by_method(*filters, remote_dir=args.remote_dir,
                  dest=args.local_dir, count=args.n_files)
    except KeyboardInterrupt:
        pass


def sync_loop(filters, args):
    while True:
        logger.info("Waiting for newly arrived files...")
        try:
            sync.by_new_arrivals(
                *filters, remote_dir=args.remote_dir, dest=args.local_dir)
        except KeyboardInterrupt:
            break
        except RequestException as e:
            logger.error("Trying again after request failure: {}".format(
                         str(e)))
            time.sleep(3)


def print_file_list(filters, args):
    files = command.list_files(*filters, remote_dir=args.remote_dir)
    files = list(files)
    title = "Files in {}".format(args.remote_dir)
    print(title)
    print("=" * len(title))
    print("\n".join(f.filename for f in files))
    print("({:d} files)\n".format(len(files)))
    

def print_file_count(filters, args):
    files = command.list_files(*filters, remote_dir=args.remote_dir)
    n_files = len(list(files))
    title = "Number of files in {}".format(args.remote_dir)
    print("\n{}\n{}".format(title, "=" * len(title)))
    print(n_files)


if __name__ == "__main__":
    with cgi.session:
        run()
 
