/*
 * @(#)FileInfo.java
 *
 * Copyright (c) 2002-2003 JSCAPE
 * 1147 S. 53rd Pl., Mesa, Arizona, 85206, U.S.A.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * JSCAPE. ("Confidential Information").  You shall not disclose such
 * Confidential Information and shall use it only in accordance with
 * the terms of the license agreement you entered into with JSCAPE.
 */

/*
 * Classname: FileInfo
 *
 * Version: 1.0
 *
 * Author: Alex Usun
 */
package com.jscape.util;

import java.io.File;
import java.util.Comparator;

import static com.jscape.util.Parameters.assertGreaterOrEqual;
import static com.jscape.util.Parameters.assertNotNull;

/**
 * @author Alex Usun
 */
public class FileInfo {

    public static final char DIRECTORY = 'd';
    public static final char REGULAR = '-';
    public static final int DIRECTORY_LINKS = 3;
    public static final int FILE_LINKS = 1;

    private String path;
    private String name;
    private char type;
    private int inode;
    private long length;
    private String user;
    private String group;
    private long modificationTime;
    private boolean readable;
    private boolean writable;
    private boolean permissionsUpdatable;
    private boolean encryptable;

    public static FileInfo forFile(String path, File file) {
        return new FileInfo(path,
                            file.getName(),
                            file.isDirectory() ? DIRECTORY : REGULAR,
                            file.isDirectory() ? DIRECTORY_LINKS : FILE_LINKS,
                            file.length(),
                            "",
                            "",
                            file.lastModified(),
                            file.canRead(),
                            file.canWrite(),
                            true,
                            false);
    }

    public FileInfo(String path,
                    String name,
                    char type,
                    int inode,
                    long length,
                    String user,
                    String group,
                    long modificationTime,
                    boolean readable,
                    boolean writable,
                    boolean permissionsUpdatable,
                    boolean encryptable) {
        assertNotNull(path);
        this.path = path;

        assertNotNull(name);
        this.name = name;

        this.type = type;
        this.inode = inode;
        this.length = length;

        assertNotNull(user);
        this.user = user;

        assertNotNull(group);
        this.group = group;

        this.modificationTime = modificationTime;
        this.readable = readable;
        this.writable = writable;
        this.permissionsUpdatable = permissionsUpdatable;
        this.encryptable = encryptable;
    }

    public String getPath() {
        return this.path;
    }

    public void setPath(String value) {
        this.path = value;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        assertNotNull(name);
        this.name = name;
    }

    public char getType() {
        return this.type;
    }

    public void setType(char type) {
        this.type = type;
    }

    public int getInode() {
        return this.inode;
    }

    public void setInode(int inode) {
        this.inode = inode;
    }

    public long getLength() {
        return this.length;
    }

    public void setLength(long val) {
        assertGreaterOrEqual(val, 0, "Bad length value.");
        this.length = val;
    }

    public String getUser() {
        return this.user;
    }

    public void setUser(String user) {
        assertNotNull(user);
        this.user = user;
    }

    public String getGroup() {
        return this.group;
    }

    public void setGroup(String group) {
        assertNotNull(group);
        this.group = group;
    }

    public long getModificationTime() {
        return this.modificationTime;
    }

    public void setModificationTime(long time) {
        this.modificationTime = time;
    }

    public boolean isReadable() {
        return this.readable;
    }

    public void setReadable(boolean val) {
        this.readable = val;
    }

    public boolean isWritable() {
        return this.writable;
    }

    public void setWritable(boolean val) {
        this.writable = val;
    }

    public boolean canUpdatePermissions() {
        return this.permissionsUpdatable;
    }

    public void setPermissionsUpdatable(boolean val) {
        this.permissionsUpdatable = val;
    }

    public boolean isEncryptable() {
        return this.encryptable;
    }

    public boolean isDirectory() {
        return this.type == DIRECTORY;
    }

    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }

        if (o == null || !getClass().equals(o.getClass())) {
            return false;
        }

        final FileInfo that = (FileInfo) o;

        return this.name.equals(that.name);
    }

    public int hashCode() {
        return this.name.hashCode();
    }

    @Override
    public String toString() {
        return "FileInfo {"
                + "path='" + this.path + '\''
                + ", name='" + this.name + '\''
                + ", type=" + this.type
                + ", inode=" + this.inode
                + ", length=" + this.length
                + ", user='" + this.user + '\''
                + ", group='" + this.group + '\''
                + ", modificationTime=" + this.modificationTime
                + ", readable=" + this.readable
                + ", writable=" + this.writable
                + ", permissionsUpdatable=" + this.permissionsUpdatable
                + ", encryptable=" + this.encryptable
                + '}';
    }

    public interface Filter {

        Filter NULL = new Filter() {
            @Override
            public boolean accepts(FileInfo value) {
                return true;
            }
        };

        boolean accepts(FileInfo value);

    }

    public static class NaturalComparator
            implements Comparator<FileInfo> {

        public int compare(FileInfo file1, FileInfo file2) {
            if (file1.getType() == FileInfo.DIRECTORY && file2.getType() != FileInfo.DIRECTORY) {
                return -1;
            }

            if (file1.getType() != FileInfo.DIRECTORY && file2.getType() == FileInfo.DIRECTORY) {
                return 1;
            }

            return file1.getName().compareToIgnoreCase(file2.getName());
        }

    }

}
