#!/usr/bin/env python3

import os
import click
import time
import threading

from pathlib import Path
import inotify.adapters

from preprocess import Preprocessor
import process

class Runner:
    image_extensions = [
        "PNG",
        "TIF",
        "TIFF",
        "PPM",
        "PGM",
        "JPG",
        "JPEG",
        "BMP"
    ]
    all_image_extensions = Preprocessor.extensions + image_extensions
    last_timestamp = None

    def __init__(self, args):
        self.args = args
        self.worker = threading.Thread(target=self.process_files)
        self.condition = threading.Condition()
        self.done = False
        self.exclude = None
        self.current_file = None
        self.worker.start()

    def is_image_extension(self, in_filename):
        filename = Path(in_filename)
        ext = str(filename.suffix).upper()[1:]
        if ext in self.all_image_extensions:
            return True

        return False
    
    def process_files(self):
        while not self.done:
            with self.condition:
                self.condition.wait()
                filename = self.current_file
                if self.done:
                    print("exiting worker")
                    break

            if filename is not None:
                print(f"processing file {filename}")
                self.exclude = filename + ".tiff"
                proc_start = time.time()
                process.run_mtfmapper(input=filename, verbose=False, args=self.args)
                proc_end = time.time()
                if self.last_timestamp is not None:
                    elapsed = proc_end - self.last_timestamp
                else:
                    elapsed = -1
                print(f"processing time = {proc_end - proc_start:.3f} s, frame-to-frame time = {elapsed:.3f} s")
                self.last_timestamp = time.time()
            
    def consider_file(self, filename):
        if self.is_image_extension(filename):
            if self.exclude is None or filename != (self.exclude): 
                with self.condition:
                    self.current_file = filename
                    self.condition.notify()

        return True
    
    def stop(self):
        with self.condition:
            self.done = True
            self.condition.notify_all()
        self.worker.join()

@click.command()
@click.option('--path', required=True, help="Specify the path to monitor")
@click.option('--args', default="", help="Additional arguments to pass to MTF Mapper, quoted as '-t 0.3 --bayer green', for example")
def main(path, args):

    i = inotify.adapters.Inotify()
    i.add_watch(path)
    print(f"added path={path} to watch")
    runner = Runner(args)

    try:
        while True:
            for event in i.event_gen(yield_nones=False):
                (_, type_names, path, filename) = event

                full_path = os.path.join(path, filename)

                if "IN_CLOSE_WRITE" in type_names:
                    runner.consider_file(full_path)

    except KeyboardInterrupt:
        print("Stopped watching.")

    runner.stop()


if __name__ == "__main__":
    main()
