import os
import subprocess as sp
import time
import psutil
import stat
import sys
import logging
from watchdog.observers.polling import PollingObserver
from watchdog.events import FileSystemEventHandler
from threading import Thread
from CommonCode import wq

from CommonCode.settings import get_logger, LogColorize
import argparse
pfm = LogColorize.watch_and_fix_permissions
if not ('__file__' in vars() or '__file__' in globals()):
    __file__ = '/home/thebears/Source/pipelines/00_watch_for_new_videos/watch_and_fix_permissions.py'

parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
sys.path.append(parent_dir)

from common import settings
default_dir_watch = settings.dir_watch
# %%
logger = get_logger(__name__,'/var/log/ml_vision_logs/00_watch_and_fix_permissions', stdout=True, systemd=False, level = logging.INFO)

logger.info(pfm(f"Starting watch_and_fix_permissions.py"))

try:
    from CommonCode import kwq
    publish = kwq.producer.send
    topic = kwq.TOPICS.exit_00_videos_to_score_detection
except Exception as e:
    logger.error("ERROR WHEN IMPORTING KAFKA:"+ str(e))

def decide_to_put_in_queue(file_name):
    disqualifiers = list()
    disqualifiers.append("_reduced" in file_name)
    disqualifiers.append("_trimmed" in file_name)

    disqualified = any(disqualifiers)

    if file_name.endswith(".mp4") and not disqualified:
        return True
    else:
        return False



class logic_execute(Thread):
    def __init__(self, event):
        logging.debug(f"EVENT: {event}")
        Thread.__init__(self)
        self.event = event

    def run(self):
        event = self.event
        if isinstance(event, str):
            src_path = event
        else:
            src_path = event.src_path

        filef = os.path.abspath(os.path.join(os.getcwd(), src_path))
        logging.debug(f"GOT_FILE: {pfm(filef)}")

        broke_out = False
        for i in range(120):
            files = list()
            for proc in psutil.process_iter():
                try:
                    if "ftp" in proc.name():
                        files.append(proc.open_files())
                except Exception:
                    pass
                
            f = list()
            for x in files:
                f.extend(x)

            if any([filef == e.path for e in f]):
                pass
            else:
                if decide_to_put_in_queue(filef):
                    dirname = os.path.dirname(filef)
                    foldmode = stat.S_IMODE(os.stat(dirname).st_mode)
                    if oct(foldmode) != "0o777":
                        os.system(f"sudo chmod 777 {dirname}")

                    logging.info(f"SETTING_PERMISSIONS: {dirname}")
                    broke_out = True
                    break

            time.sleep(1)
            
        if not broke_out:
            logging.info(f"TIMED_OUT: {filef}")

            
        chand = {"root": os.path.dirname(filef), "name": os.path.basename(filef)}
        
        try:
            os.chmod(filef, 0o777)
        except Exception as e:
            logging.error(e)

        if decide_to_put_in_queue(filef):
            logging.info(f"QUEUE_PUT: {pfm(filef)}")
            wq.publish(wq.TOPICS.ml_vision_to_score, filef)
            try:
                future = publish(topic, key=filef, value={"filepath": filef})
            except Exception as e:
                logging.error("KAFKA ERROR " + str(e))
        else:
            logging.info(f"QUEUE_DO_NOT_PUT: {filef}")


class Handler(FileSystemEventHandler):
    def on_created(self, event):
        try:
            self.handle_it(event)
        except Exception as e:
            logging.error(e)

    def handle_it(self, event):
        if event.is_directory:
            return
        lclass = logic_execute(event)
        lclass.start()


def observe_path(path):
    event_handler = Handler()
    observer = PollingObserver()
    logger.info(f"Monitoring {path}")
    observer.schedule(event_handler, path, recursive=True)
    observer.start()
    observer.is_alive()
    return observer


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        prog="Watch and Fix Permissions And Push to Kafka Queue"
    )

    parser.add_argument("paths", nargs="*", help="Paths to monitor", default=())

    args, _ = parser.parse_known_args()
    paths = args.paths
    if len(paths) == 0:
        paths = default_dir_watch
    observers = [observe_path(path) for path in paths]
    
    try:
        while True:
            time.sleep(1)
    except Exception as e:
        logging.error(str(e))

    for observer in observers:
        observer.stop()
        observer.join()
