// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.plugins.pathprovider;

import android.content.Context;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import androidx.annotation.NonNull;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.SettableFuture;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.MethodCodec;
import io.flutter.plugin.common.StandardMethodCodec;
import io.flutter.util.PathUtils;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class PathProviderPlugin implements FlutterPlugin, MethodCallHandler {
  static final String TAG = "PathProviderPlugin";
  private Context context;
  private MethodChannel channel;
  private PathProviderImpl impl;

  /**
   * An abstraction over how to access the paths in a thread-safe manner.
   *
   * <p>We need this so on versions of Flutter that support Background Platform Channels this plugin
   * can take advantage of it.
   *
   * <p>This can be removed after https://github.com/flutter/engine/pull/29147 becomes available on
   * the stable branch.
   */
  private interface PathProviderImpl {
    void getTemporaryDirectory(@NonNull Result result);

    void getApplicationDocumentsDirectory(@NonNull Result result);

    void getStorageDirectory(@NonNull Result result);

    void getExternalCacheDirectories(@NonNull Result result);

    void getExternalStorageDirectories(@NonNull String directoryName, @NonNull Result result);

    void getApplicationSupportDirectory(@NonNull Result result);
  }

  /** The implementation for getting system paths that executes from the platform */
  private class PathProviderPlatformThread implements PathProviderImpl {
    private final Executor uiThreadExecutor = new UiThreadExecutor();
    private final Executor executor =
        Executors.newSingleThreadExecutor(
            new ThreadFactoryBuilder()
                .setNameFormat("path-provider-background-%d")
                .setPriority(Thread.NORM_PRIORITY)
                .build());

    public void getTemporaryDirectory(@NonNull Result result) {
      executeInBackground(() -> getPathProviderTemporaryDirectory(), result);
    }

    public void getApplicationDocumentsDirectory(@NonNull Result result) {
      executeInBackground(() -> getPathProviderApplicationDocumentsDirectory(), result);
    }

    public void getStorageDirectory(@NonNull Result result) {
      executeInBackground(() -> getPathProviderStorageDirectory(), result);
    }

    public void getExternalCacheDirectories(@NonNull Result result) {
      executeInBackground(() -> getPathProviderExternalCacheDirectories(), result);
    }

    public void getExternalStorageDirectories(
        @NonNull String directoryName, @NonNull Result result) {
      executeInBackground(() -> getPathProviderExternalStorageDirectories(directoryName), result);
    }

    public void getApplicationSupportDirectory(@NonNull Result result) {
      executeInBackground(() -> PathProviderPlugin.this.getApplicationSupportDirectory(), result);
    }

    private <T> void executeInBackground(Callable<T> task, Result result) {
      final SettableFuture<T> future = SettableFuture.create();
      Futures.addCallback(
          future,
          new FutureCallback<T>() {
            public void onSuccess(T answer) {
              result.success(answer);
            }

            public void onFailure(Throwable t) {
              result.error(t.getClass().getName(), t.getMessage(), null);
            }
          },
          uiThreadExecutor);
      executor.execute(
          () -> {
            try {
              future.set(task.call());
            } catch (Throwable t) {
              future.setException(t);
            }
          });
    }
  }

  /** The implementation for getting system paths that executes from a background thread. */
  private class PathProviderBackgroundThread implements PathProviderImpl {
    public void getTemporaryDirectory(@NonNull Result result) {
      result.success(getPathProviderTemporaryDirectory());
    }

    public void getApplicationDocumentsDirectory(@NonNull Result result) {
      result.success(getPathProviderApplicationDocumentsDirectory());
    }

    public void getStorageDirectory(@NonNull Result result) {
      result.success(getPathProviderStorageDirectory());
    }

    public void getExternalCacheDirectories(@NonNull Result result) {
      result.success(getPathProviderExternalCacheDirectories());
    }

    public void getExternalStorageDirectories(
        @NonNull String directoryName, @NonNull Result result) {
      result.success(getPathProviderExternalStorageDirectories(directoryName));
    }

    public void getApplicationSupportDirectory(@NonNull Result result) {
      result.success(PathProviderPlugin.this.getApplicationSupportDirectory());
    }
  }

  public PathProviderPlugin() {}

  private void setup(BinaryMessenger messenger, Context context) {
    String channelName = "plugins.flutter.io/path_provider";
    // TODO(gaaclarke): Remove reflection guard when https://github.com/flutter/engine/pull/29147
    // becomes available on the stable branch.
    try {
      Class methodChannelClass = Class.forName("io.flutter.plugin.common.MethodChannel");
      Class taskQueueClass = Class.forName("io.flutter.plugin.common.BinaryMessenger$TaskQueue");
      Method makeBackgroundTaskQueue = messenger.getClass().getMethod("makeBackgroundTaskQueue");
      Object taskQueue = makeBackgroundTaskQueue.invoke(messenger);
      Constructor<MethodChannel> constructor =
          methodChannelClass.getConstructor(
              BinaryMessenger.class, String.class, MethodCodec.class, taskQueueClass);
      channel =
          constructor.newInstance(messenger, channelName, StandardMethodCodec.INSTANCE, taskQueue);
      impl = new PathProviderBackgroundThread();
      Log.d(TAG, "Use TaskQueues.");
    } catch (Exception ex) {
      channel = new MethodChannel(messenger, channelName);
      impl = new PathProviderPlatformThread();
      Log.d(TAG, "Don't use TaskQueues.");
    }
    this.context = context;
    channel.setMethodCallHandler(this);
  }

  @SuppressWarnings("deprecation")
  public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registrar registrar) {
    PathProviderPlugin instance = new PathProviderPlugin();
    instance.setup(registrar.messenger(), registrar.context());
  }

  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
    setup(binding.getBinaryMessenger(), binding.getApplicationContext());
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    channel.setMethodCallHandler(null);
    channel = null;
  }

  @Override
  public void onMethodCall(MethodCall call, @NonNull Result result) {
    switch (call.method) {
      case "getTemporaryDirectory":
        impl.getTemporaryDirectory(result);
        break;
      case "getApplicationDocumentsDirectory":
        impl.getApplicationDocumentsDirectory(result);
        break;
      case "getStorageDirectory":
        impl.getStorageDirectory(result);
        break;
      case "getExternalCacheDirectories":
        impl.getExternalCacheDirectories(result);
        break;
      case "getExternalStorageDirectories":
        final Integer type = call.argument("type");
        final String directoryName = StorageDirectoryMapper.androidType(type);
        impl.getExternalStorageDirectories(directoryName, result);
        break;
      case "getApplicationSupportDirectory":
        impl.getApplicationSupportDirectory(result);
        break;
      default:
        result.notImplemented();
    }
  }

  private String getPathProviderTemporaryDirectory() {
    return context.getCacheDir().getPath();
  }

  private String getApplicationSupportDirectory() {
    return PathUtils.getFilesDir(context);
  }

  private String getPathProviderApplicationDocumentsDirectory() {
    return PathUtils.getDataDirectory(context);
  }

  private String getPathProviderStorageDirectory() {
    final File dir = context.getExternalFilesDir(null);
    if (dir == null) {
      return null;
    }
    return dir.getAbsolutePath();
  }

  private List<String> getPathProviderExternalCacheDirectories() {
    final List<String> paths = new ArrayList<String>();

    if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
      for (File dir : context.getExternalCacheDirs()) {
        if (dir != null) {
          paths.add(dir.getAbsolutePath());
        }
      }
    } else {
      File dir = context.getExternalCacheDir();
      if (dir != null) {
        paths.add(dir.getAbsolutePath());
      }
    }

    return paths;
  }

  private List<String> getPathProviderExternalStorageDirectories(String type) {
    final List<String> paths = new ArrayList<String>();

    if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
      for (File dir : context.getExternalFilesDirs(type)) {
        if (dir != null) {
          paths.add(dir.getAbsolutePath());
        }
      }
    } else {
      File dir = context.getExternalFilesDir(type);
      if (dir != null) {
        paths.add(dir.getAbsolutePath());
      }
    }

    return paths;
  }

  private static class UiThreadExecutor implements Executor {
    private final Handler handler = new Handler(Looper.getMainLooper());

    @Override
    public void execute(Runnable command) {
      handler.post(command);
    }
  }
}
