/**
 * ZipSnap 2.1
 * Copyright 2007 Zach Scrivena
 * 2007-08-26
 * zachscrivena@gmail.com
 * http://zipsnap.sourceforge.net/
 *
 * ZipSnap is a simple command-line incremental backup tool for directories.
 *
 * TERMS AND CONDITIONS:
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package zipsnap;

import java.io.File;
import java.util.ArrayList;
import java.util.List;


/**
 * Represent a file/directory with all its attributes.
 */
public class FileUnit implements Comparable<FileUnit>
{
    /** neutral and relative pathname of file/directory */
    public String name;

    /** native and relative pathname of file/directory */
    public final String nativeName;

    /** File object representing this file/directory (native and absolute pathname) */
    public final File file;

    /** true if this FileUnit represents a directory; false otherwise */
    public final boolean isDirectory;

    /** size of file/directory in bytes (size of directory is defined as zero) */
    public long size = 0;

    /** last-modified time in milliseconds since the epoch (00:00:00 GMT, January 1, 1970) */
    public long time = 0;

    /** CRC-32 checksum of file/directory (CRC-32 checksum of a directory is defined as zero) */
    private long crc = -1;

    /** snapshots that contain this file/directory */
    public final List<Integer> snapshots = new ArrayList<Integer>();


    /**
    * Constructor. For performance reasons, only a subset of the fields
    * are required for initialization.
    *
    * @param nativeName
    *     native and relative pathname of file/directory
    * @param file
    *     File object representing this file/directory (native and absolute pathname)
    * @param isDirectory
    *     true if this FileUnit represents a directory; false otherwise
    */
    FileUnit(
            final String nativeName,
            final File file,
            final boolean isDirectory)
    {
        this.nativeName = nativeName;
        this.file = file;
        this.isDirectory = isDirectory;
    }


    /**
    * Compare this object to the specified object;
    * only the name field is compared.
    */
    @Override
    public int compareTo(
            final FileUnit o)
    {
        return this.name.compareTo(o.name);
    }


    /**
    * Indicate if this object is equal to the specified object;
    * only the name field is checked for equality.
    */
    @Override
    public boolean equals(
            final Object o)
    {
        if (o instanceof FileUnit)
            return this.name.equals(((FileUnit) o).name);

        return false;
    }


    /**
    * Return a hash code value for this object;
    * only the name field is used in generating the hash code.
    */
    @Override
    public int hashCode()
    {
        return this.name.hashCode();
    }


    /**
    * Return true if this file/directory matches the defined filter, or
    * if no filter is defined; false otherwise.
    */
    public boolean matchesFilter()
    {
        if (ZipSnap.filterPattern == null)
            return true;

        /* match string */
        final String s;

        if (ZipSnap.filterFullPathname)
        {
            /* match against full (relative) pathname */
            s = this.nativeName;
        }
        else
        {
            /* match against file/directory name only */
            s = FileIO.trimTrailingSeparator(this.file.getName()) +
                    (this.isDirectory ? File.separatorChar : "");
        }

        return ZipSnap.filterPattern.matcher(s).matches();
    }


    /**
    * Return the CRC-32 checksum of this file/directory.
    */
    public long getCrc()
    {
        /* compute "just-in-time" */
        if (this.crc < 0)
        {
            final FileIO.ComputeFileCRC32Result result = FileIO.computeFileCRC32(this.file);

            if (result.success)
            {
                this.crc = result.checksum;
            }
            else
            {
                ErrorWarningHandler.reportWarning("Unable to compute CRC-32 checksum of file \"" +
                        this.file.getPath() + "\".\nThe CRC-32 checksum of this file will be assumed to be 0.");

                this.crc = 0L;
            }
        }

        return this.crc;
    }


    /**
    * Set the CRC-32 checksum of this file/directory.
    */
    public void setCrc(
            final long crc)
    {
        this.crc = crc;
    }
}