/*
 * Copyright (C) 2019 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 android.os.incremental;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.RemoteException;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.UUID;

/**
 * Provides operations on an Incremental File System directory, using IncrementalServiceNative.
 * Example usage:
 *
 * <blockquote><pre>
 * IncrementalManager manager = (IncrementalManager) getSystemService(Context.INCREMENTAL_SERVICE);
 * IncrementalStorage storage = manager.openStorage("/path/to/incremental/dir");
 * storage.makeDirectory("subdir");
 * </pre></blockquote>
 *
 * @hide
 */
public final class IncrementalStorage {
    private static final String TAG = "IncrementalStorage";
    private final int mId;
    private final IIncrementalManagerNative mService;


    public IncrementalStorage(@NonNull IIncrementalManagerNative is, int id) {
        mService = is;
        mId = id;
    }

    public int getId() {
        return mId;
    }

    /**
     * Temporarily bind-mounts the current storage directory to a target directory. The bind-mount
     * will NOT be preserved between device reboots.
     *
     * @param targetPath Absolute path to the target directory.
     */
    public void bind(@NonNull String targetPath) throws IOException {
        bind("", targetPath);
    }

    /**
     * Temporarily bind-mounts a subdir under the current storage directory to a target directory.
     * The bind-mount will NOT be preserved between device reboots.
     *
     * @param sourcePath Source path as a relative path under current storage
     *                   directory.
     * @param targetPath Absolute path to the target directory.
     */
    public void bind(@NonNull String sourcePath, @NonNull String targetPath)
            throws IOException {
        try {
            int res = mService.makeBindMount(mId, sourcePath, targetPath,
                    IIncrementalManagerNative.BIND_TEMPORARY);
            if (res < 0) {
                throw new IOException("bind() failed with errno " + -res);
            }
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }


    /**
     * Permanently bind-mounts the current storage directory to a target directory. The bind-mount
     * WILL be preserved between device reboots.
     *
     * @param targetPath Absolute path to the target directory.
     */
    public void bindPermanent(@NonNull String targetPath) throws IOException {
        bindPermanent("", targetPath);
    }

    /**
     * Permanently bind-mounts a subdir under the current storage directory to a target directory.
     * The bind-mount WILL be preserved between device reboots.
     *
     * @param sourcePath Relative path under the current storage directory.
     * @param targetPath Absolute path to the target directory.
     */
    public void bindPermanent(@NonNull String sourcePath, @NonNull String targetPath)
            throws IOException {
        try {
            int res = mService.makeBindMount(mId, sourcePath, targetPath,
                    IIncrementalManagerNative.BIND_PERMANENT);
            if (res < 0) {
                throw new IOException("bind() permanent failed with errno " + -res);
            }
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * Unbinds a bind mount.
     *
     * @param targetPath Absolute path to the target directory.
     */
    public void unBind(@NonNull String targetPath) throws IOException {
        try {
            int res = mService.deleteBindMount(mId, targetPath);
            if (res < 0) {
                throw new IOException("unbind() failed with errno " + -res);
            }
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * Creates a sub-directory under the current storage directory.
     *
     * @param path Relative path of the sub-directory, e.g., "subdir"
     */
    public void makeDirectory(@NonNull String path) throws IOException {
        try {
            int res = mService.makeDirectory(mId, path);
            if (res < 0) {
                throw new IOException("makeDirectory() failed with errno " + -res);
            }
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * Creates a sub-directory under the current storage directory. If its parent dirs do not exist,
     * create the parent dirs as well.
     *
     * @param path Full path.
     */
    public void makeDirectories(@NonNull String path) throws IOException {
        try {
            int res = mService.makeDirectories(mId, path);
            if (res < 0) {
                throw new IOException("makeDirectory() failed with errno " + -res);
            }
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * Creates a file under the current storage directory.
     *
     * @param path             Relative path of the new file.
     * @param size             Size of the new file in bytes.
     * @param metadata         Metadata bytes.
     */
    public void makeFile(@NonNull String path, long size, @Nullable UUID id,
            @Nullable byte[] metadata, int hashAlgorithm, @Nullable byte[] rootHash,
            @Nullable byte[] additionalData, @Nullable byte[] signature) throws IOException {
        try {
            final IncrementalNewFileParams params = new IncrementalNewFileParams();
            params.size = size;
            params.metadata = metadata;
            params.fileId = idToBytes(id);
            if (hashAlgorithm != 0 || signature != null) {
                params.signature = new IncrementalSignature();
                params.signature.hashAlgorithm = hashAlgorithm;
                params.signature.rootHash = rootHash;
                params.signature.additionalData = additionalData;
                params.signature.signature = signature;
            }
            int res = mService.makeFile(mId, path, params);
            if (res != 0) {
                throw new IOException("makeFile() failed with errno " + -res);
            }
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * Creates a file in Incremental storage. The content of the file is mapped from a range inside
     * a source file in the same storage.
     *
     * @param destPath           Target full path.
     * @param sourcePath         Source full path.
     * @param rangeStart         Starting offset (in bytes) in the source file.
     * @param rangeEnd           Ending offset (in bytes) in the source file.
     */
    public void makeFileFromRange(@NonNull String destPath,
            @NonNull String sourcePath, long rangeStart, long rangeEnd) throws IOException {
        try {
            int res = mService.makeFileFromRange(mId, destPath, sourcePath,
                    rangeStart, rangeEnd);
            if (res < 0) {
                throw new IOException("makeFileFromRange() failed, errno " + -res);
            }
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * Creates a hard-link between two paths, which can be under different storages but in the same
     * Incremental File System.
     *
     * @param sourcePath    The absolute path of the source.
     * @param destStorage   The target storage of the link target.
     * @param destPath      The absolute path of the target.
     */
    public void makeLink(@NonNull String sourcePath, IncrementalStorage destStorage,
            @NonNull String destPath) throws IOException {
        try {
            int res = mService.makeLink(mId, sourcePath, destStorage.getId(),
                    destPath);
            if (res < 0) {
                throw new IOException("makeLink() failed with errno " + -res);
            }
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * Deletes a hard-link under the current storage directory.
     *
     * @param path The absolute path of the target.
     */
    public void unlink(@NonNull String path) throws IOException {
        try {
            int res = mService.unlink(mId, path);
            if (res < 0) {
                throw new IOException("unlink() failed with errno " + -res);
            }
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * Rename an old file name to a new file name under the current storage directory.
     *
     * @param sourcepath Old file path as a full path to the storage directory.
     * @param destpath   New file path as a full path to the storage directory.
     */
    public void moveFile(@NonNull String sourcepath,
            @NonNull String destpath) throws IOException {
        //TODO(zyy): implement using rename(2) when confirmed that IncFS supports it.
        try {
            int res = mService.makeLink(mId, sourcepath, mId, destpath);
            if (res < 0) {
                throw new IOException("moveFile() failed at makeLink(), errno " + -res);
            }
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
        try {
            mService.unlink(mId, sourcepath);
        } catch (RemoteException ignored) {
        }
    }

    /**
     * Move a directory, which is bind-mounted to a given storage, to a new location. The bind mount
     * will be persistent between reboots.
     *
     * @param sourcePath The old path of the directory as an absolute path.
     * @param destPath   The new path of the directory as an absolute path, expected to already
     *                   exist.
     */
    public void moveDir(@NonNull String sourcePath, @NonNull String destPath) throws IOException {
        if (!new File(destPath).exists()) {
            throw new IOException("moveDir() requires that destination dir already exists.");
        }
        try {
            int res = mService.makeBindMount(mId, sourcePath, destPath,
                    IIncrementalManagerNative.BIND_PERMANENT);
            if (res < 0) {
                throw new IOException("moveDir() failed at making bind mount, errno " + -res);
            }
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
        try {
            mService.deleteBindMount(mId, sourcePath);
        } catch (RemoteException ignored) {
        }
    }

    /**
     * Checks whether a file under the current storage directory is fully loaded.
     *
     * @param path The relative path of the file.
     * @return True if the file is fully loaded.
     */
    public boolean isFileFullyLoaded(@NonNull String path) {
        return isFileRangeLoaded(path, 0, -1);
    }

    /**
     * Checks whether a range in a file if loaded.
     *
     * @param path The relative path of the file.
     * @param start            The starting offset of the range.
     * @param end              The ending offset of the range.
     * @return True if the file is fully loaded.
     */
    public boolean isFileRangeLoaded(@NonNull String path, long start, long end) {
        try {
            return mService.isFileRangeLoaded(mId, path, start, end);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
            return false;
        }
    }

    /**
     * Returns the metadata object of an IncFs File.
     *
     * @param path The relative path of the file.
     * @return Byte array that contains metadata bytes.
     */
    @Nullable
    public byte[] getFileMetadata(@NonNull String path) {
        try {
            return mService.getMetadataByPath(mId, path);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
            return null;
        }
    }

    private static final int UUID_BYTE_SIZE = 16;

    /**
     * Converts UUID to a byte array usable for Incremental API calls
     *
     * @param id The id to convert
     * @return Byte array that contains the same ID.
     */
    public static byte[] idToBytes(UUID id) {
        if (id == null) {
            return null;
        }
        final ByteBuffer buf = ByteBuffer.wrap(new byte[UUID_BYTE_SIZE]);
        buf.putLong(id.getMostSignificantBits());
        buf.putLong(id.getLeastSignificantBits());
        return buf.array();
    }

    /**
     * Converts UUID from a byte array usable for Incremental API calls
     *
     * @param bytes The id in byte array format, 16 bytes long
     * @return UUID constructed from the byte array.
     */
    public static UUID bytesToId(byte[] bytes) {
        if (bytes.length != UUID_BYTE_SIZE) {
            throw new IllegalArgumentException("Expected array of size " + UUID_BYTE_SIZE
                                               + ", got " + bytes.length);
        }
        final ByteBuffer buf = ByteBuffer.wrap(bytes);
        long msb = buf.getLong();
        long lsb = buf.getLong();
        return new UUID(msb, lsb);
    }

    /**
     * Returns the metadata object of an IncFs File.
     *
     * @param id The file id.
     * @return Byte array that contains metadata bytes.
     */
    @Nullable
    public byte[] getFileMetadata(@NonNull UUID id) {
        try {
            final byte[] rawId = idToBytes(id);
            return mService.getMetadataById(mId, rawId);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
            return null;
        }
    }

    /**
     * Informs the data loader service associated with the current storage to start data loader
     *
     * @return True if data loader is successfully started.
     */
    public boolean startLoading() {
        try {
            return mService.startLoading(mId);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
            return false;
        }
    }
}
