/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache license, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the license for the specific language governing permissions and
 * limitations under the license.
 */

package org.apache.logging.log4j.core.appender.rolling.action;

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;
import java.util.Objects;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.status.StatusLogger;

/**
 * FileVisitor that deletes files that are accepted by all PathFilters. Directories are ignored.
 */
public class DeletingVisitor extends SimpleFileVisitor<Path> {
    private static final Logger LOGGER = StatusLogger.getLogger();

    private final Path basePath;
    private final boolean testMode;
    private final List<? extends PathCondition> pathConditions;

    /**
     * Constructs a new DeletingVisitor.
     * 
     * @param basePath used to relativize paths
     * @param pathConditions objects that need to confirm whether a file can be deleted
     * @param testMode if true, files are not deleted but instead a message is printed to the <a
     *            href="http://logging.apache.org/log4j/2.x/manual/configuration.html#StatusMessages">status logger</a>
     *            at INFO level. Users can use this to do a dry run to test if their configuration works as expected.
     */
    public DeletingVisitor(final Path basePath, final List<? extends PathCondition> pathConditions,
            final boolean testMode) {
        this.testMode = testMode;
        this.basePath = Objects.requireNonNull(basePath, "basePath");
        this.pathConditions = Objects.requireNonNull(pathConditions, "pathConditions");
        for (final PathCondition condition : pathConditions) {
            condition.beforeFileTreeWalk();
        }
    }

    @Override
    public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
        for (final PathCondition pathFilter : pathConditions) {
            final Path relative = basePath.relativize(file);
            if (!pathFilter.accept(basePath, relative, attrs)) {
                LOGGER.trace("Not deleting base={}, relative={}", basePath, relative);
                return FileVisitResult.CONTINUE;
            }
        }
        if (isTestMode()) {
            LOGGER.info("Deleting {} (TEST MODE: file not actually deleted)", file);
        } else {
            delete(file);
        }
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException ioException) throws IOException {
        // LOG4J2-2677: Appenders may rollover and purge in parallel. SimpleVisitor rethrows exceptions from
        // failed attempts to load file attributes.
        if (ioException instanceof NoSuchFileException) {
            LOGGER.info("File {} could not be accessed, it has likely already been deleted", file, ioException);
            return FileVisitResult.CONTINUE;
        } else {
            return super.visitFileFailed(file, ioException);
        }
    }

    /**
     * Deletes the specified file.
     * 
     * @param file the file to delete
     * @throws IOException if a problem occurred deleting the file
     */
    protected void delete(final Path file) throws IOException {
        LOGGER.trace("Deleting {}", file);
        Files.deleteIfExists(file);
    }

    /**
     * Returns {@code true} if files are not deleted even when all conditions accept a path, {@code false} otherwise.
     * 
     * @return {@code true} if files are not deleted even when all conditions accept a path, {@code false} otherwise
     */
    public boolean isTestMode() {
        return testMode;
    }
}
