package hudson.node_monitors;

import hudson.model.Computer;
import hudson.node_monitors.DiskSpaceMonitorDescriptor.DiskSpace;
import java.text.ParseException;
import java.util.logging.Logger;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;

/**
 * @author Kohsuke Kawaguchi
 * @see DiskSpaceMonitorDescriptor
 */
public abstract class AbstractDiskSpaceMonitor extends NodeMonitor {
    /**
     * The free space threshold, below which the node monitor will be triggered.
     * This is a human readable string representation as entered by the user, so that we can retain the original notation.
     */
    public final String freeSpaceThreshold;

    protected AbstractDiskSpaceMonitor(String threshold) throws ParseException {
        this.freeSpaceThreshold = threshold;
        DiskSpace.parse(threshold); // make sure it parses
    }

    protected AbstractDiskSpaceMonitor() {
        this.freeSpaceThreshold = "1GB";
    }

    public long getThresholdBytes() {
        if (freeSpaceThreshold == null)
            return DEFAULT_THRESHOLD; // backward compatibility with the data format that didn't have 'freeSpaceThreshold'
        try {
            return DiskSpace.parse(freeSpaceThreshold).size;
        } catch (ParseException e) {
            return DEFAULT_THRESHOLD;
        }
    }

    @Override
    public Object data(Computer c) {
        DiskSpace size = markNodeOfflineIfDiskspaceIsTooLow(c);

        // mark online (again), if free space is over threshold
        if (size != null && size.size > getThresholdBytes() && c.isOffline() && c.getOfflineCause() instanceof DiskSpace)
            if (this.getClass().equals(((DiskSpace) c.getOfflineCause()).getTrigger()))
                if (getDescriptor().markOnline(c)) {
                    LOGGER.info(Messages.DiskSpaceMonitor_MarkedOnline(c.getDisplayName()));
                }
        return size;
    }

    /**
     * Marks the given node as offline if free disk space is below the configured threshold.
     * @param c the node
     * @return the free space
     * @since 1.521
     */
    @Restricted(NoExternalUse.class)
    public DiskSpace markNodeOfflineIfDiskspaceIsTooLow(Computer c) {
        DiskSpace size = (DiskSpace) super.data(c);
        if (size != null && size.size < getThresholdBytes()) {
            size.setTriggered(this.getClass(), true);
            if (getDescriptor().markOffline(c, size))  {
                LOGGER.warning(Messages.DiskSpaceMonitor_MarkedOffline(c.getDisplayName()));
            }
        }
        return size;
    }

    private static final Logger LOGGER = Logger.getLogger(AbstractDiskSpaceMonitor.class.getName());
    private static final long DEFAULT_THRESHOLD = 1024L * 1024 * 1024;
}
