// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.core.asset.monitor;

import java.io.FileNotFoundException;
import java.nio.file.NoSuchFileException;
import com.hypixel.hytale.logger.sentry.SkipSentryException;
import java.util.logging.Level;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.concurrent.ScheduledFuture;
import javax.annotation.Nonnull;
import java.nio.file.Path;
import com.hypixel.hytale.logger.HytaleLogger;

public class FileChangeTask implements Runnable
{
    public static final HytaleLogger LOGGER;
    private static final long FILE_SIZE_CHECK_DELAY_MILLIS = 200L;
    private final AssetMonitor assetMonitor;
    @Nonnull
    private final Path path;
    @Nonnull
    private final PathEvent pathEvent;
    private final boolean createdOrModified;
    @Nonnull
    private final ScheduledFuture<?> task;
    private long lastSize;
    
    public FileChangeTask(final AssetMonitor assetMonitor, @Nonnull final Path path, @Nonnull final PathEvent pathEvent) throws IOException {
        this.assetMonitor = assetMonitor;
        this.path = path;
        this.pathEvent = pathEvent;
        this.createdOrModified = (pathEvent.getEventKind() == EventKind.ENTRY_CREATE || pathEvent.getEventKind() == EventKind.ENTRY_MODIFY);
        long size = 0L;
        if (this.createdOrModified) {
            final BasicFileAttributes fileAttributes = Files.readAttributes(path, BasicFileAttributes.class, new LinkOption[0]);
            if (!fileAttributes.isDirectory()) {
                size = fileAttributes.size();
            }
        }
        this.lastSize = size;
        this.task = AssetMonitor.runTask(this, 200L);
    }
    
    public AssetMonitor getAssetMonitor() {
        return this.assetMonitor;
    }
    
    @Nonnull
    public Path getPath() {
        return this.path;
    }
    
    @Nonnull
    public PathEvent getPathEvent() {
        return this.pathEvent;
    }
    
    @Override
    public void run() {
        try {
            if (this.createdOrModified) {
                if (!Files.exists(this.path, new LinkOption[0])) {
                    FileChangeTask.LOGGER.at(Level.WARNING).log("The asset file '%s' was deleted before we could load/update it!", this.path);
                    this.cancelSchedule();
                    return;
                }
                final BasicFileAttributes fileAttributes = Files.readAttributes(this.path, BasicFileAttributes.class, new LinkOption[0]);
                if (!fileAttributes.isDirectory()) {
                    final long size = fileAttributes.size();
                    if (size > this.lastSize) {
                        FileChangeTask.LOGGER.at(Level.FINEST).log("File increased in size: %s, %s, %d > %d", this.path, this.pathEvent, size, this.lastSize);
                        this.lastSize = size;
                        this.assetMonitor.markChanged(this.path);
                        return;
                    }
                }
            }
            this.cancelSchedule();
            this.assetMonitor.onDelayedChange(this.path, this.pathEvent);
        }
        catch (final NoSuchFileException | FileNotFoundException e) {
            FileChangeTask.LOGGER.at(Level.SEVERE).withCause(new SkipSentryException(e)).log("The asset file '%s' was deleted before we could load/update it!", this.path);
        }
        catch (final Throwable e2) {
            FileChangeTask.LOGGER.at(Level.SEVERE).withCause(e2).log("Failed to handle file change %s", this.path);
        }
    }
    
    public void cancelSchedule() {
        FileChangeTask.LOGGER.at(Level.FINEST).log("cancelSchedule(): %s", this);
        this.assetMonitor.removeFileChangeTask(this);
        if (this.task != null && !this.task.isDone()) {
            this.task.cancel(false);
        }
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "FileChangeTask{path=" + String.valueOf(this.path) + ", eventKind=" + String.valueOf(this.pathEvent) + ", lastSize=" + this.lastSize;
    }
    
    static {
        LOGGER = HytaleLogger.forEnclosingClass();
    }
}
