package org.apache.logging.log4j.core.config;

import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class FileConfigurationMonitor implements ConfigurationMonitor {
   private static final int MASK = 15;
   private static final int MIN_INTERVAL = 5;
   private static final int MILLIS_PER_SECOND = 1000;
   private final File file;
   private long lastModified;
   private final List<ConfigurationListener> listeners;
   private final int interval;
   private long nextCheck;
   private final AtomicInteger counter = new AtomicInteger(0);
   private static final Lock LOCK = new ReentrantLock();
   private final Reconfigurable reconfigurable;

   public FileConfigurationMonitor(Reconfigurable reconfigurable, File file, List<ConfigurationListener> listeners, int interval) {
      this.reconfigurable = reconfigurable;
      this.file = file;
      this.lastModified = file.lastModified();
      this.listeners = listeners;
      this.interval = (interval < 5 ? 5 : interval) * 1000;
      this.nextCheck = System.currentTimeMillis() + (long)interval;
   }

   public void checkConfiguration() {
      long current = System.currentTimeMillis();
      if ((this.counter.incrementAndGet() & 15) == 0 && current >= this.nextCheck) {
         LOCK.lock();

         try {
            this.nextCheck = current + (long)this.interval;
            if (this.file.lastModified() > this.lastModified) {
               this.lastModified = this.file.lastModified();
               Iterator i$ = this.listeners.iterator();

               while(i$.hasNext()) {
                  ConfigurationListener listener = (ConfigurationListener)i$.next();
                  Thread thread = new Thread(new FileConfigurationMonitor.ReconfigurationWorker(listener, this.reconfigurable));
                  thread.setDaemon(true);
                  thread.start();
               }
            }
         } finally {
            LOCK.unlock();
         }
      }

   }

   private class ReconfigurationWorker implements Runnable {
      private final ConfigurationListener listener;
      private final Reconfigurable reconfigurable;

      public ReconfigurationWorker(ConfigurationListener listener, Reconfigurable reconfigurable) {
         this.listener = listener;
         this.reconfigurable = reconfigurable;
      }

      public void run() {
         this.listener.onChange(this.reconfigurable);
      }
   }
}
