package com.base.task.core.listener;

import com.base.task.TaskInitialize;
import com.base.task.core.TaskCache;
import com.base.task.model.Task;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.filefilter.FileFileFilter;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.HiddenFileFilter;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class FileMonitor {

    private FileAlterationMonitor monitor = new FileAlterationMonitor(1000);

    private static FileMonitor fileMonitor = new FileMonitor();

    private FileMonitor(){}

    public static FileMonitor getInstance(){
        return fileMonitor;
    }

    Map<Task,FileAlterationObserver> fileAlterationObserverMap=new HashMap<>();
    Map<Task,TaskResultListener> taskTaskResultListenerMap=new HashMap<>();


    public void stopListenerFile(File file,Task task){
        monitor.getObservers().forEach(e->{
            if (file.getPath().equals(e.getDirectory().getPath()+File.separator+task.getOkFileName())){
                try {
                    e.destroy();
                    if (fileAlterationObserverMap.get(task)!=null){
                        if (taskTaskResultListenerMap.get(task)!=null){
                            fileAlterationObserverMap.get(task).removeListener(taskTaskResultListenerMap.get(task));
                            monitor.removeObserver(fileAlterationObserverMap.get(task));
                            fileAlterationObserverMap.remove(task);
                            taskTaskResultListenerMap.remove(task);
                        }
                    }
                } catch (Exception ex) {
                    log.error(ex.getMessage(),ex);
                }
            }
        });
    }

    public void addListener(Task task){
        IOFileFilter dir= FileFilterUtils.and(
                FileFilterUtils.directoryFileFilter(),
                HiddenFileFilter.VISIBLE
        );
        IOFileFilter files=FileFilterUtils.and(
                FileFilterUtils.fileFileFilter(),
                FileFilterUtils.suffixFileFilter(task.getOkFileName())
        );
        IOFileFilter filter=FileFilterUtils.or(dir,files);
        FileAlterationObserver observer = new FileAlterationObserver(new File(task.getOkFilePath()),filter);
        monitor.addObserver(observer);
        fileAlterationObserverMap.put(task,observer);
        TaskResultListener taskResultListener=new TaskResultListener(task);
        observer.addListener(taskResultListener);
        taskTaskResultListenerMap.put(task,taskResultListener);
    }

    public void removeListener(Task task){
        IOFileFilter dir= FileFilterUtils.and(
                FileFilterUtils.directoryFileFilter(),
                HiddenFileFilter.VISIBLE
        );
        IOFileFilter files=FileFilterUtils.and(
                FileFilterUtils.fileFileFilter(),
                FileFilterUtils.suffixFileFilter(task.getOkFileName())
        );
        IOFileFilter filter=FileFilterUtils.or(dir,files);
        FileAlterationObserver observer = new FileAlterationObserver(new File(task.getOkFilePath()),filter);
        monitor.removeObserver(observer);
        observer.removeListener(new TaskResultListener(task));
    }

    public void monitorStart(){
        try {
            monitor.start();
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }
    }

    public void monitorStop(){
        try {
            monitor.stop();
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }
    }


}
