/*
 * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.xbib.net.mail.mbox;

import java.io.File;
import java.io.FileDescriptor;
import java.util.StringTokenizer;

@SuppressWarnings("serial")
public class UNIXFile extends File {

    protected static final boolean loaded;
    protected static final int lockType;

    public UNIXFile(String name) {
        super(name);
    }

    // lock type enum
    protected static final int NONE = 0;
    protected static final int NATIVE = 1;
    protected static final int JAVA = 2;

    static {
        String lt = System.getProperty("mail.mbox.locktype", "native");
        int type = NATIVE;
        if (lt.equalsIgnoreCase("none"))
            type = NONE;
        else if (lt.equalsIgnoreCase("java"))
            type = JAVA;
        lockType = type;

        boolean lloaded = false;
        if (lockType == NATIVE) {
            try {
                System.loadLibrary("mbox");
                lloaded = true;
            } catch (UnsatisfiedLinkError e) {
                String classpath = System.getProperty("java.class.path");
                String sep = System.getProperty("path.separator");
                String arch = System.getProperty("os.arch");
                StringTokenizer st = new StringTokenizer(classpath, sep);
                while (st.hasMoreTokens()) {
                    String path = st.nextToken();
                    if (path.endsWith("/classes") ||
                            path.endsWith("/mail.jar") ||
                            path.endsWith("/jakarta.mail.jar")) {
                        int i = path.lastIndexOf('/');
                        String libdir = path.substring(0, i + 1) + "lib/";
                        String lib = libdir + arch + "/libmbox.so";
                        try {
                            System.load(lib);
                            lloaded = true;
                            break;
                        } catch (UnsatisfiedLinkError e2) {
                            lib = libdir + "libmbox.so";
                            try {
                                System.load(lib);
                                lloaded = true;
                                break;
                            } catch (UnsatisfiedLinkError e3) {
                                continue;
                            }
                        }
                    }
                }
            }
        }
        loaded = lloaded;
        if (loaded)
            initIDs(FileDescriptor.class, FileDescriptor.in);
    }

    /**
     * Return the access time of the file.
     */
    public static long lastAccessed(File file) {
        return lastAccessed0(file.getPath());
    }

    public long lastAccessed() {
        return lastAccessed0(getPath());
    }

    private static native void initIDs(Class<FileDescriptor> fdClass,
                                       FileDescriptor stdin);

    /**
     * Lock the file referred to by fd.  The string mode is "r"
     * for a read lock or "rw" for a write lock.  Don't block
     * if lock can't be acquired.
     */
    public static boolean lock(FileDescriptor fd, String mode) {
        return lock(fd, mode, false);
    }

    /**
     * Lock the file referred to by fd.  The string mode is "r"
     * for a read lock or "rw" for a write lock.  If block is set,
     * block waiting for the lock if necessary.
     */
    private static boolean lock(FileDescriptor fd, String mode, boolean block) {
        //return loaded && lock0(fd, mode);
        if (loaded) {
            boolean ret;
            ret = lock0(fd, mode, block);
            return ret;
        }
        return false;
    }

    private static native boolean lock0(FileDescriptor fd, String mode, boolean block);

    public static native long lastAccessed0(String name);
}
