/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed 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 com.android.internal.os;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.ProxyFileDescriptorCallback;
import android.system.ErrnoException;
import android.system.OsConstants;
import android.util.Log;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ThreadFactory;

public class FuseAppLoop implements Handler.Callback {
    private static final String TAG = "FuseAppLoop";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    public static final int ROOT_INODE = 1;
    private static final int MIN_INODE = 2;
    private static final ThreadFactory sDefaultThreadFactory = new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, TAG);
        }
    };
    private static final int FUSE_OK = 0;
    private static final int ARGS_POOL_SIZE = 50;

    private final Object mLock = new Object();
    private final int mMountPointId;
    private final Thread mThread;

    @GuardedBy("mLock")
    private final SparseArray<CallbackEntry> mCallbackMap = new SparseArray<>();

    @GuardedBy("mLock")
    private final BytesMap mBytesMap = new BytesMap();

    @GuardedBy("mLock")
    private final LinkedList<Args> mArgsPool = new LinkedList<>();

    /**
     * Sequential number can be used as file name and inode in AppFuse.
     * 0 is regarded as an error, 1 is mount point. So we start the number from 2.
     */
    @GuardedBy("mLock")
    private int mNextInode = MIN_INODE;

    @GuardedBy("mLock")
    private long mInstance;

    public FuseAppLoop(
            int mountPointId, @NonNull ParcelFileDescriptor fd, @Nullable ThreadFactory factory) {
        mMountPointId = mountPointId;
        if (factory == null) {
            factory = sDefaultThreadFactory;
        }
        mInstance = native_new(fd.detachFd());
        mThread = factory.newThread(() -> {
            native_start(mInstance);
            synchronized (mLock) {
                native_delete(mInstance);
                mInstance = 0;
                mBytesMap.clear();
            }
        });
        mThread.start();
    }

    public int registerCallback(@NonNull ProxyFileDescriptorCallback callback,
            @NonNull Handler handler) throws FuseUnavailableMountException {
        synchronized (mLock) {
            Objects.requireNonNull(callback);
            Objects.requireNonNull(handler);
            Preconditions.checkState(
                    mCallbackMap.size() < Integer.MAX_VALUE - MIN_INODE, "Too many opened files.");
            Preconditions.checkArgument(
                    Thread.currentThread().getId() != handler.getLooper().getThread().getId(),
                    "Handler must be different from the current thread");
            if (mInstance == 0) {
                throw new FuseUnavailableMountException(mMountPointId);
            }
            int id;
            while (true) {
                id = mNextInode;
                mNextInode++;
                if (mNextInode < 0) {
                    mNextInode = MIN_INODE;
                }
                if (mCallbackMap.get(id) == null) {
                    break;
                }
            }
            mCallbackMap.put(id, new CallbackEntry(
                    callback, new Handler(handler.getLooper(), this)));
            return id;
        }
    }

    public void unregisterCallback(int id) {
        synchronized (mLock) {
            mCallbackMap.remove(id);
        }
    }

    public int getMountPointId() {
        return mMountPointId;
    }

    // Defined in fuse.h
    private static final int FUSE_LOOKUP = 1;
    private static final int FUSE_GETATTR = 3;
    private static final int FUSE_OPEN = 14;
    private static final int FUSE_READ = 15;
    private static final int FUSE_WRITE = 16;
    private static final int FUSE_RELEASE = 18;
    private static final int FUSE_FSYNC = 20;

    // Defined in FuseBuffer.h
    private static final int FUSE_MAX_WRITE = 128 * 1024;

    @Override
    public boolean handleMessage(Message msg) {
        final Args args = (Args) msg.obj;
        final CallbackEntry entry = args.entry;
        final long inode = args.inode;
        final long unique = args.unique;
        final int size = args.size;
        final long offset = args.offset;
        final byte[] data = args.data;

        try {
            switch (msg.what) {
                case FUSE_LOOKUP: {
                    final long fileSize = entry.callback.onGetSize();
                    synchronized (mLock) {
                        if (mInstance != 0) {
                            native_replyLookup(mInstance, unique, inode, fileSize);
                        }
                        recycleLocked(args);
                    }
                    break;
                }
                case FUSE_GETATTR: {
                    final long fileSize = entry.callback.onGetSize();
                    synchronized (mLock) {
                        if (mInstance != 0) {
                            native_replyGetAttr(mInstance, unique, inode, fileSize);
                        }
                        recycleLocked(args);
                    }
                    break;
                }
                case FUSE_READ:
                    final int readSize = entry.callback.onRead(
                            offset, size, data);
                    synchronized (mLock) {
                        if (mInstance != 0) {
                            native_replyRead(mInstance, unique, readSize, data);
                        }
                        recycleLocked(args);
                    }
                    break;
                case FUSE_WRITE:
                    final int writeSize = entry.callback.onWrite(offset, size, data);
                    synchronized (mLock) {
                        if (mInstance != 0) {
                            native_replyWrite(mInstance, unique, writeSize);
                        }
                        recycleLocked(args);
                    }
                    break;
                case FUSE_FSYNC:
                    entry.callback.onFsync();
                    synchronized (mLock) {
                        if (mInstance != 0) {
                            native_replySimple(mInstance, unique, FUSE_OK);
                        }
                        recycleLocked(args);
                    }
                    break;
                case FUSE_RELEASE:
                    entry.callback.onRelease();
                    synchronized (mLock) {
                        if (mInstance != 0) {
                            native_replySimple(mInstance, unique, FUSE_OK);
                        }
                        mBytesMap.stopUsing(inode);
                        recycleLocked(args);
                    }
                    break;
                default:
                    throw new IllegalArgumentException("Unknown FUSE command: " + msg.what);
            }
        } catch (Exception error) {
            synchronized (mLock) {
                Log.e(TAG, "", error);
                replySimpleLocked(unique, getError(error));
                recycleLocked(args);
            }
        }

        return true;
    }

    // Called by JNI.
    @SuppressWarnings("unused")
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    private void onCommand(int command, long unique, long inode, long offset, int size,
            byte[] data) {
        synchronized (mLock) {
            try {
                final Args args;
                if (mArgsPool.size() == 0) {
                    args = new Args();
                } else {
                    args = mArgsPool.pop();
                }
                args.unique = unique;
                args.inode = inode;
                args.offset = offset;
                args.size = size;
                args.data = data;
                args.entry = getCallbackEntryOrThrowLocked(inode);
                if (!args.entry.handler.sendMessage(
                        Message.obtain(args.entry.handler, command, 0, 0, args))) {
                    throw new ErrnoException("onCommand", OsConstants.EBADF);
                }
            } catch (Exception error) {
                replySimpleLocked(unique, getError(error));
            }
        }
    }

    // Called by JNI.
    @SuppressWarnings("unused")
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    private byte[] onOpen(long unique, long inode) {
        synchronized (mLock) {
            try {
                final CallbackEntry entry = getCallbackEntryOrThrowLocked(inode);
                if (entry.opened) {
                    throw new ErrnoException("onOpen", OsConstants.EMFILE);
                }
                if (mInstance != 0) {
                    native_replyOpen(mInstance, unique, /* fh */ inode);
                    entry.opened = true;
                    return mBytesMap.startUsing(inode);
                }
            } catch (ErrnoException error) {
                replySimpleLocked(unique, getError(error));
            }
            return null;
        }
    }

    private static int getError(@NonNull Exception error) {
        if (error instanceof ErrnoException) {
            final int errno = ((ErrnoException) error).errno;
            if (errno != OsConstants.ENOSYS) {
                return -errno;
            }
        }
        return -OsConstants.EBADF;
    }

    @GuardedBy("mLock")
    private CallbackEntry getCallbackEntryOrThrowLocked(long inode) throws ErrnoException {
        final CallbackEntry entry = mCallbackMap.get(checkInode(inode));
        if (entry == null) {
            throw new ErrnoException("getCallbackEntryOrThrowLocked", OsConstants.ENOENT);
        }
        return entry;
    }

    @GuardedBy("mLock")
    private void recycleLocked(Args args) {
        if (mArgsPool.size() < ARGS_POOL_SIZE) {
            mArgsPool.add(args);
        }
    }

    @GuardedBy("mLock")
    private void replySimpleLocked(long unique, int result) {
        if (mInstance != 0) {
            native_replySimple(mInstance, unique, result);
        }
    }

    native long native_new(int fd);
    native void native_delete(long ptr);
    native void native_start(long ptr);

    native void native_replySimple(long ptr, long unique, int result);
    native void native_replyOpen(long ptr, long unique, long fh);
    native void native_replyLookup(long ptr, long unique, long inode, long size);
    native void native_replyGetAttr(long ptr, long unique, long inode, long size);
    native void native_replyWrite(long ptr, long unique, int size);
    native void native_replyRead(long ptr, long unique, int size, byte[] bytes);

    private static int checkInode(long inode) {
        Preconditions.checkArgumentInRange(inode, MIN_INODE, Integer.MAX_VALUE, "checkInode");
        return (int) inode;
    }

    public static class UnmountedException extends Exception {}

    private static class CallbackEntry {
        final ProxyFileDescriptorCallback callback;
        final Handler handler;
        boolean opened;

        CallbackEntry(ProxyFileDescriptorCallback callback, Handler handler) {
            this.callback = Objects.requireNonNull(callback);
            this.handler = Objects.requireNonNull(handler);
        }

        long getThreadId() {
            return handler.getLooper().getThread().getId();
        }
    }

    /**
     * Entry for bytes map.
     */
    private static class BytesMapEntry {
        int counter = 0;
        byte[] bytes = new byte[FUSE_MAX_WRITE];
    }

    /**
     * Map between inode and byte buffer.
     */
    private static class BytesMap {
        final Map<Long, BytesMapEntry> mEntries = new HashMap<>();

        byte[] startUsing(long inode) {
            BytesMapEntry entry = mEntries.get(inode);
            if (entry == null) {
                entry = new BytesMapEntry();
                mEntries.put(inode, entry);
            }
            entry.counter++;
            return entry.bytes;
        }

        void stopUsing(long inode) {
            final BytesMapEntry entry = mEntries.get(inode);
            Objects.requireNonNull(entry);
            entry.counter--;
            if (entry.counter <= 0) {
                mEntries.remove(inode);
            }
        }

        void clear() {
            mEntries.clear();
        }
    }

    private static class Args {
        long unique;
        long inode;
        long offset;
        int size;
        byte[] data;
        CallbackEntry entry;
    }
}
