package com.ReactNativeBlobUtil;

import android.os.Build;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;

import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Nullable;

public class ReactNativeBlobUtil extends ReactContextBaseJavaModule {

    private final ReactNativeBlobUtilImpl delegate;

    public ReactNativeBlobUtil(ReactApplicationContext reactContext) {
        super(reactContext);
        delegate = new ReactNativeBlobUtilImpl(reactContext);
    }

    // Required for rn built in EventEmitter Calls.
    @ReactMethod
    public void addListener(String eventName) {

    }

    @ReactMethod
    public void removeListeners(Integer count) {

    }

    @NonNull
    @Override
    public String getName() {
        return ReactNativeBlobUtilImpl.NAME;
    }

    @Override
    public Map<String, Object> getConstants() {
        Map<String, Object> res = new HashMap<>();
        res.putAll(ReactNativeBlobUtilFS.getSystemfolders(this.getReactApplicationContext()));
        res.putAll(ReactNativeBlobUtilFS.getLegacySystemfolders(this.getReactApplicationContext()));

        return res;
    }

    @ReactMethod
    public void createFile(final String path, final String content, final String encode, final Promise promise) {
        delegate.createFile(path, content, encode, promise);
    }

    @ReactMethod
    public void createFileASCII(final String path, final ReadableArray dataArray, final Promise promise) {
        delegate.createFileASCII(path, dataArray, promise);
    }

    @ReactMethod
    public void actionViewIntent(String path, String mime, @Nullable String chooserTitle, final Promise promise) {
        delegate.actionViewIntent(path, mime, chooserTitle, promise);
    }

    @ReactMethod
    public void writeArrayChunk(final String streamId, final ReadableArray dataArray, final Callback callback) {
        delegate.writeArrayChunk(streamId, dataArray, callback);
    }

    @ReactMethod
    public void unlink(String path, Callback callback) {
        delegate.unlink(path, callback);
    }

    @ReactMethod
    public void mkdir(String path, Promise promise) {
        delegate.mkdir(path, promise);
    }

    @ReactMethod
    public void exists(String path, Callback callback) {
        delegate.exists(path, callback);
    }

    @ReactMethod
    public void cp(final String path, final String dest, final Callback callback) {
        delegate.cp(path, dest, callback);
    }

    @ReactMethod
    public void mv(String path, String dest, Callback callback) {
        delegate.mv(path, dest, callback);
    }

    @ReactMethod
    public void ls(String path, Promise promise) {
        delegate.ls(path, promise);
    }

    @ReactMethod
    public void writeStream(String path, String encode, boolean append, Callback callback) {
        delegate.writeStream(path, encode, append, callback);
    }

    @ReactMethod
    public void writeChunk(String streamId, String data, Callback callback) {
        delegate.writeChunk(streamId, data, callback);
    }

    @ReactMethod
    public void closeStream(String streamId, Callback callback) {
        delegate.closeStream(streamId, callback);
    }

    @ReactMethod
    public void removeSession(ReadableArray paths, Callback callback) {
        delegate.removeSession(paths, callback);
    }

    @ReactMethod
    public void readFile(final String path, final String encoding, final boolean transformFile, final Promise promise) {
        delegate.readFile(path, encoding, transformFile, promise);
    }

    @ReactMethod
    public void writeFileArray(final String path, final ReadableArray data, final boolean append, final Promise promise) {
        delegate.writeFileArray(path, data, append, promise);
    }

    @ReactMethod
    public void writeFile(final String path, final String encoding, final String data, final boolean transformFile, final boolean append, final Promise promise) {
        delegate.writeFile(path, encoding, data, transformFile, append, promise);
    }

    @ReactMethod
    public void lstat(String path, Callback callback) {
        delegate.lstat(path, callback);
    }

    @ReactMethod
    public void stat(String path, Callback callback) {
        delegate.stat(path, callback);
    }

    @ReactMethod
    public void scanFile(final ReadableArray pairs, final Callback callback) {
        delegate.scanFile(pairs, callback);
    }

    @ReactMethod
    public void hash(final String path, final String algorithm, final Promise promise) {
        delegate.hash(path, algorithm, promise);
    }

    /**
     * @param path       Stream file path
     * @param encoding   Stream encoding, should be one of `base64`, `ascii`, and `utf8`
     * @param bufferSize Stream buffer size, default to 4096 or 4095(base64).
     */
    @ReactMethod
    public void readStream(final String path, final String encoding, final int bufferSize, final int tick, final String streamId) {
        delegate.readStream(path, encoding, bufferSize, tick, streamId);
    }

    @ReactMethod
    public void cancelRequest(String taskId, Callback callback) {
        delegate.cancelRequest(taskId, callback);
    }

    @ReactMethod
    public void slice(String src, String dest, double start, double end, Promise promise) {
        delegate.slice(src, dest, (long) start, (long) end, promise);
    }

    @ReactMethod
    public void enableProgressReport(String taskId, int interval, int count) {
        delegate.enableProgressReport(taskId, interval, count);
    }

    @ReactMethod
    public void df(final Callback callback) {
        delegate.df(callback);
    }


    @ReactMethod
    public void enableUploadProgressReport(String taskId, int interval, int count) {
        delegate.enableUploadProgressReport(taskId, interval, count);
    }

    @ReactMethod
    public void fetchBlob(ReadableMap options, String taskId, String method, String url, ReadableMap headers, String body, final Callback callback) {
        delegate.fetchBlob(options, taskId, method, url, headers, body, callback);
    }

    @ReactMethod
    public void fetchBlobForm(ReadableMap options, String taskId, String method, String url, ReadableMap headers, ReadableArray body, final Callback callback) {
        delegate.fetchBlobForm(options, taskId, method, url, headers, body, callback);
    }

    @ReactMethod
    public void getContentIntent(String mime, Promise promise) {
        delegate.getContentIntent(mime, promise);
    }

    @ReactMethod
    public void addCompleteDownload(ReadableMap config, Promise promise) {
        delegate.addCompleteDownload(config, promise);
    }

    @ReactMethod
    public void getSDCardDir(Promise promise) {
        delegate.getSDCardDir(promise);
    }

    @ReactMethod
    public void getSDCardApplicationDir(Promise promise) {
        delegate.getSDCardApplicationDir(promise);
    }

    @ReactMethod
    public void createMediaFile(ReadableMap filedata, String mt, Promise promise) {
        delegate.createMediaFile(filedata, mt, promise);
    }

    @ReactMethod
    public void writeToMediaFile(String fileUri, String path, boolean transformFile, Promise promise) {
        delegate.writeToMediaFile(fileUri, path, transformFile, promise);
    }

    @RequiresApi(api = Build.VERSION_CODES.Q)
    @ReactMethod
    public void copyToInternal(String contentUri, String destpath, Promise promise) {
        delegate.copyToInternal(contentUri, destpath, promise);
    }

    @RequiresApi(api = Build.VERSION_CODES.Q)
    @ReactMethod
    public void getBlob(String contentUri, String encoding, Promise promise) {
        delegate.getBlob(contentUri, encoding, promise);
    }

    @ReactMethod
    public void copyToMediaStore(ReadableMap filedata, String mt, String path, Promise promise) {
        delegate.copyToMediaStore(filedata, mt, path, promise);
    }
}
