/*
 * 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.felix.fileinstall.internal;

import java.io.Closeable;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;
import java.util.zip.CRC32;

/**
 * A Scanner object is able to detect and report new, modified
 * and deleted files.
 *
 * The scanner use an internal checksum to identify the signature
 * of a file or directory.  The checksum will change if the file
 * or any of the directory's child is modified.
 *
 * In addition, if the scanner detects a change on a given file, it
 * will wait until the checksum does not change anymore before reporting
 * the change on this file.  This allows to not report the change until
 * a big copy if complete for example.
 */
public class Scanner implements Closeable {

    public final static String SUBDIR_MODE_JAR = "jar";
    public final static String SUBDIR_MODE_SKIP = "skip";
    public final static String SUBDIR_MODE_RECURSE = "recurse";

    final File directory;
    final FilenameFilter filter;
    final boolean jarSubdir;
    final boolean skipSubdir;
    final boolean recurseSubdir;

    // Store checksums of files or directories
    Map<File, Long> lastChecksums = new HashMap<File, Long>();
    Map<File, Long> storedChecksums = new HashMap<File, Long>();

    /**
     * Create a scanner for the specified directory
     *
     * @param directory the directory to scan
     */
    public Scanner(File directory)
    {
        this(directory, null, null);
    }

    /**
     * Create a scanner for the specified directory and file filter
     *
     * @param directory the directory to scan
     * @param filterString a filter for file names
     * @param subdirMode to use when scanning
     */
    public Scanner(File directory, final String filterString, String subdirMode)
    {
        this.directory = canon(directory);
        if (filterString != null && filterString.length() > 0)
        {
            this.filter = new FilenameFilter()
            {
                Pattern pattern = Pattern.compile(filterString);
                public boolean accept(File dir, String name)
                {
                    return pattern.matcher(name).matches();
                }
            };
        }
        else
        {
            this.filter = null;
        }
        this.jarSubdir = subdirMode == null || SUBDIR_MODE_JAR.equals(subdirMode);
        this.skipSubdir = SUBDIR_MODE_SKIP.equals(subdirMode);
        this.recurseSubdir = SUBDIR_MODE_RECURSE.equals(subdirMode);
    }

    /**
     * Initialize the list of known files.
     * This should be called before the first scan to initialize
     * the list of known files.  The purpose is to be able to detect
     * files that have been deleted while the scanner was inactive.
     *
     * @param checksums a map of checksums
     */
    public void initialize(Map<File, Long> checksums)
    {
        storedChecksums.putAll(checksums);
    }

    /**
     * Report a set of new, modified or deleted files.
     * Modifications are checked against a computed checksum on some file
     * attributes to detect any modification.
     * Upon restart, such checksums are not known so that all files will
     * be reported as modified. 
     *
     * @param reportImmediately report all files immediately without waiting for the checksum to be stable
     * @return a list of changes on the files included in the directory
     */
    public Set<File> scan(boolean reportImmediately)
    {

        File[] list = directory.listFiles();
        Set<File> files = processFiles(reportImmediately, list);
        return new TreeSet<>(files);
    }

    private Set<File> processFiles(boolean reportImmediately, File[] list)
    {
        if (list == null)
        {
            return new HashSet<>();
        }
        Set<File> files = new HashSet<File>();
        Set<File> removed = new HashSet<File>(storedChecksums.keySet());
        for (File file : list)
        {
            if (file.isDirectory())
            {
                if (skipSubdir)
                {
                    continue;
                } 
                else if (recurseSubdir)
                {
                    files.addAll(processFiles(reportImmediately, file.listFiles()));
                    continue;
                }
            }
            else {
                if (!filter.accept(file.getParentFile(),file.getName())){
                    continue;
                }
            }
            long lastChecksum = lastChecksums.get(file) != null ? (Long) lastChecksums.get(file) : 0;
            long storedChecksum = storedChecksums.get(file) != null ? (Long) storedChecksums.get(file) : 0;
            long newChecksum = checksum(file);
            lastChecksums.put(file, newChecksum);
            // Only handle file when it does not change anymore and it has changed
            // since last reported
            if ((newChecksum == lastChecksum || reportImmediately) && newChecksum != storedChecksum)
            {
                storedChecksums.put(file, newChecksum);
                files.add(file);
            }
            removed.remove(file);
        }
        // Make sure we'll handle a file that has been deleted
        files.addAll(removed);
        for (File file : removed)
        {
            // Remove no longer used checksums
            lastChecksums.remove(file);
            storedChecksums.remove(file);
        }
        return files;
    }

    public void close() throws IOException {
    }

    private static File canon(File file)
    {
        try
        {
            return file.getCanonicalFile();
        }
        catch (IOException e)
        {
            return file;
        }
    }

    /**
     * Retrieve the previously computed checksum for a give file.
     *
     * @param file the file to retrieve the checksum
     * @return the checksum
     */
    public long getChecksum(File file)
    {
        Long c = storedChecksums.get(file);
        return c != null ? c : 0;
    }

    /**
      * Update the checksum of a file if that file is already known locally.
      */
    public void updateChecksum(File file)
    {
        if (file != null && storedChecksums.containsKey(file))
        {
            long newChecksum = checksum(file);
            storedChecksums.put(file, newChecksum);
        }
    }

    /**
     * Compute a cheksum for the file or directory that consists of the name, length and the last modified date
     * for a file and its children in case of a directory
     *
     * @param file the file or directory
     * @return a checksum identifying any change
     */
    static long checksum(File file)
    {
        CRC32 crc = new CRC32();
        checksum(file, crc);
        return crc.getValue();
    }

    private static void checksum(File file, CRC32 crc)
    {
        crc.update(file.getName().getBytes());
        if (file.isFile())
        {
            checksum(file.lastModified(), crc);
            checksum(file.length(), crc);
        }
        else if (file.isDirectory())
        {
            File[] children = file.listFiles();
            if (children != null)
            {
                for (File aChildren : children)
                {
                    checksum(aChildren, crc);
                }
            }
        }
    }

    private static void checksum(long l, CRC32 crc)
    {
        for (int i = 0; i < 8; i++)
        {
            crc.update((int) (l & 0x000000ff));
            l >>= 8;
        }
    }

}
