package com.datarecovery.master.utils.filedetect;

import static android.content.Context.POWER_SERVICE;

import android.content.Context;
import android.os.CancellationSignal;
import android.os.PowerManager;
import android.text.TextUtils;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;

import com.datarecovery.master.utils.BrandUtil;
import com.datarecovery.master.utils.xfile.XFile;
import com.datarecovery.master.utils.xfile.XFileSearch;

import org.reactivestreams.Publisher;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import atmob.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import atmob.reactivex.rxjava3.core.BackpressureStrategy;
import atmob.reactivex.rxjava3.core.Flowable;
import atmob.reactivex.rxjava3.core.FlowableOnSubscribe;
import atmob.reactivex.rxjava3.functions.Function;

/**
 * 文件扫描帮助类
 */
public class FileScanHelper {

    private FileScanHelper() {

    }

    private static final List<String[]> wxDirList = new ArrayList<>();
    private static final List<String[]> galleryList = new ArrayList<>();
    private static final List<String[]> qqList = new ArrayList<>();


    static {
        initWxDir();
        initGalleryDir();
        initQQDir();
    }

    private static void initQQDir() {
        qqList.add(new String[]{"Android", "data", "com.tencent.mobileqq"});
        qqList.add(new String[]{"Android", "data", "com.tencent.tim"});
        qqList.add(new String[]{"Pictures", "QQ"});
        qqList.add(new String[]{"Download", "QQ"});
        qqList.add(new String[]{"Download", "QQMail"});
        qqList.add(new String[]{"Download", "QQBrowser"});
    }

    private static void initGalleryDir() {
        galleryList.add(new String[]{"DCIM"});
        galleryList.add(new String[]{"Pictures"});
        galleryList.add(new String[]{"Android", "data", "com.android.gallery3d"});
        galleryList.add(new String[]{"Android", "data", "com.android.gallery"});
        galleryList.addAll(getFactoryGalleryDir());
    }

    private static void initWxDir() {
        wxDirList.add(new String[]{"Android", "data", "com.tencent.mm"});
        wxDirList.add(new String[]{"DCIM", "WeixinWork"});
        wxDirList.add(new String[]{"Pictures", "WeiXin"});
        wxDirList.add(new String[]{"Download", "WeiXin"});
    }

    /**
     * 需要能单扫某个文件夹（某个app）
     */

    @IntDef({FileType.IMAGE_GALLERY, FileType.IMAGE_WEIXIN, FileType.IMAGE_QQ})
    @Retention(RetentionPolicy.SOURCE)
    public @interface RefreshScanType {
    }


    public static Flowable<List<DetectFile>> refreshImageDetect(@NonNull Context context, @RefreshScanType int scanType) {
        return Flowable.create((FlowableOnSubscribe<XFile>) emitter -> {
                    try {
                        CancellationSignal cancellationSignal = XFileSearch.searchSpecifyExternalStorageAsync(context, getImageScanDirectory(scanType), new XFileSearch.FileFilter() {
                            @Override
                            public boolean acceptFile(XFile file) {
                                return isAcceptImageFile(scanType, file);
                            }

                            @Override
                            public boolean acceptDirectory(XFile file) {
                                return isAcceptImageDirectory(scanType, file);
                            }

                            @Override
                            public boolean filterDirectory(XFile file) {
                                return isFilterImageDirectory(scanType, file);
                            }
                        }, new XFileSearch.FileSearchCallback() {
                            @Override
                            public void onStart() {

                            }

                            @Override
                            public void onEachFile(XFile file) {
                                emitter.onNext(file);
                            }

                            @Override
                            public void onFinish() {
                                emitter.onComplete();
                            }
                        });
                        emitter.setCancellable(cancellationSignal::cancel);
                    } catch (Exception e) {
                        emitter.onError(e);
                    }
                }, BackpressureStrategy.BUFFER)
                .filter(xFile -> xFile.getTag() != null)
                .flatMap((Function<XFile, Publisher<DetectFile>>) xFile -> {
                    int tag = (int) xFile.getTag();
                    switch (tag) {
                        case ImageType.IMG_MAGIC:
                        case ImageType.IMAGE_SUFFIX:
                        case ImageType.IMG_DATA:
                            return Flowable.just(new DetectFile(xFile, scanType));
                        case ImageType.XIAOMI_GALLERY_CACHE:
                            return Flowable.just(new DetectFile(xFile, FileType.IMAGE_GALLERY));
                        case ImageType.WECHAT_CACHE:
                            return ImageCacheUtil.detectWechatCache(context, xFile);
                        case ImageType.GALLERY_CACHE:
                            return ImageCacheUtil.detectGalleryCache(context, xFile);
                        case ImageType.OPPO_GALLERY_CACHE:
                            return ImageCacheUtil.detectOppoGalleryCache(context, xFile);
                        case ImageType.VIVO_GALLERY_CACHE:
                            return ImageCacheUtil.detectVivoGalleryCache(context, xFile);
                        case ImageType.MEIZU_GALLERY_CACHE:
                            return ImageCacheUtil.detectMeizuGalleryCache(context, xFile);
                        case ImageType.HUAWEI_GALLERY_CACHE:
                            return ImageCacheUtil.detectHuaweiGalleryCache(context, xFile);
                        default:
                            return Flowable.empty();
                    }
                })
                .buffer(200, TimeUnit.MILLISECONDS)
                .filter(imageFiles -> imageFiles != null && !imageFiles.isEmpty())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe(subscription -> {
                    subscription.request(Long.MAX_VALUE);
                    acquireWakeLock(context);
                })
                .doOnCancel(() -> releaseWakeLock(context))
                .doOnTerminate(() -> releaseWakeLock(context));
    }

    private static boolean isAcceptImageFile(int scanType, XFile file) {
        try {
            if (file.length() == 0) {
                return false;
            }
        } catch (Exception ignore) {
        }
        try {
            if (file.getMineType() != null && file.getMineType().startsWith("image/")) {
                file.setTag(ImageType.IMG_DATA);
                return true;
            }
        } catch (Exception ignore) {

        }
        try {
            String name = file.getName();
            if (ImageCacheUtil.isImageSuffix(name)) {
                file.setTag(ImageType.IMAGE_SUFFIX);
                return true;
            }
        } catch (Exception ignore) {
        }

        if (scanType == FileType.IMAGE_GALLERY) {
            try {
                String path = file.getPath();
                int brand = BrandUtil.getBrand();
                switch (brand) {
                    case BrandUtil.Oppo:
                        if (ImageCacheUtil.isOppoGalleryCacheFile(path)) {
                            file.setTag(ImageType.OPPO_GALLERY_CACHE);
                        }
                        return true;
                    case BrandUtil.Vivo:
                        if (ImageCacheUtil.isVivoGalleryCacheFile(path)) {
                            file.setTag(ImageType.VIVO_GALLERY_CACHE);
                        }
                        return true;
                    case BrandUtil.XiaoMi:
                        if (ImageCacheUtil.isXiaomiGalleryCacheFile(path)) {
                            file.setTag(ImageType.XIAOMI_GALLERY_CACHE);
                        }
                        return true;
                    case BrandUtil.Meizu:
                        if (ImageCacheUtil.isMeizuGalleryCacheFile(path)) {
                            file.setTag(ImageType.MEIZU_GALLERY_CACHE);
                        }
                        return true;
                    case BrandUtil.HuaWei:
                        if (ImageCacheUtil.isHuaweiGalleryCacheFile(path)) {
                            file.setTag(ImageType.HUAWEI_GALLERY_CACHE);
                        }
                        return true;
                }
            } catch (Exception ignore) {
            }
        }
        if (ImageCacheUtil.hasImgMagic(file)) {
            file.setTag(ImageType.IMG_MAGIC);
            return true;
        }
        return false;
    }


    public static boolean isAcceptImageDirectory(int scanType, XFile file) {
        if (scanType == FileType.IMAGE_GALLERY) {
            try {
                String path = file.getPath();
                if (isGalleryCacheDirectory(path)) {
                    file.setTag(ImageType.GALLERY_CACHE);
                    return true;
                }
            } catch (Exception ignore) {
            }
        }
        return false;
    }

    private static boolean isGalleryCacheDirectory(String path) {
        if (TextUtils.isEmpty(path)) {
            return false;
        }
        return path.contains("com.android.gallery3d%2Fcache") ||
                path.contains("com.android.gallery3d/cache");
    }


    private static boolean isFilterImageDirectory(@RefreshScanType int scanType, @NonNull XFile file) {
        try {
            String path = file.getPath();
            if (TextUtils.isEmpty(path)) {
                return true;
            }
            if (FileType.IMAGE_GALLERY == scanType) {
                if (path.endsWith("Pictures/QQ") || path.endsWith("Pictures%2FQQ") ||
                        path.endsWith("DCIM/WeixinWork") || path.endsWith("DCIM%2FWeixinWork") ||
                        path.endsWith("Pictures/WeiXin") || path.endsWith("Pictures%2FWeiXin")
                ) {
                    return true;
                }
            }
        } catch (Exception e) {

        }
        return false;
    }

    private static void releaseWakeLock(Context context) {
        PowerManager powerManager = (PowerManager) context.getSystemService(POWER_SERVICE);
        PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                "ImageDeepDetector::detect");
        if (wakeLock.isHeld()) {
            wakeLock.release();
        }
    }

    private static void acquireWakeLock(Context context) {
        PowerManager powerManager = (PowerManager) context.getSystemService(POWER_SERVICE);
        PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                "ImageDeepDetector::detect");
        wakeLock.acquire(10 * 60 * 1000L /*10 minutes*/);
    }

    public static List<String[]> getGallery() {
        return galleryList;
    }

    public static @NonNull List<String[]> getFactoryGalleryDir() {
        List<String[]> brandGallery = new ArrayList<>();
        int brand = BrandUtil.getBrand();
        switch (brand) {
            case BrandUtil.HuaWei:
                brandGallery.add(new String[]{"Huawei"});
                brandGallery.add(new String[]{"Android", "data", "com.huawei.photos"});
                break;
            case BrandUtil.XiaoMi:
                brandGallery.add(new String[]{"Android", "data", "com.miui.gallery"});
                break;
            case BrandUtil.Vivo:
                brandGallery.add(new String[]{"Android", "data", "com.vivo.gallery"});
                break;
            case BrandUtil.Oppo:
                brandGallery.add(new String[]{"Android", "data", "com.oppo.gallery3d"});
                break;
            case BrandUtil.Meizu:
                brandGallery.add(new String[]{"Android", "data", "com.meizu.media.gallery"});
                break;
            case BrandUtil.Samsung:
                brandGallery.add(new String[]{"Android", "data", "com.sec.android.gallery3d"});
                break;
            case BrandUtil.Smartisan:
                brandGallery.add(new String[]{"Android", "data", "com.smartisanos.gallery"});
                break;
            case BrandUtil.Lenovo:
                brandGallery.add(new String[]{"Android", "data", "com.lenovo.scg"});
                break;
            case BrandUtil.ZTE:
                brandGallery.add(new String[]{"Android", "data", "com.zte.gallery"});
                break;
            case BrandUtil.OnePlus:
                brandGallery.add(new String[]{"Android", "data", "com.oneplus.gallery"});
                break;
            case BrandUtil.Google:
                brandGallery.add(new String[]{"Android", "data", "com.google.android.apps.photos"});
                break;
            case BrandUtil.Sony:
                brandGallery.add(new String[]{"Android", "data", "com.sonyericsson.album"});
                break;
            case BrandUtil.LG:
                brandGallery.add(new String[]{"Android", "data", "com.lge.gallery3d"});
                break;
            case BrandUtil.HTC:
                brandGallery.add(new String[]{"Android", "data", "com.htc.album"});
                break;
            case BrandUtil.ASUS:
                brandGallery.add(new String[]{"Android", "data", "com.asus.gallery"});
                break;
            case BrandUtil.GIONEE:
                brandGallery.add(new String[]{"Android", "data", "com.gionee.gallery"});
                break;
            case BrandUtil.MOTOROLA:
                brandGallery.add(new String[]{"Android", "data", "com.motorola.gallery"});
                break;
            case BrandUtil.NUBIA:
                brandGallery.add(new String[]{"Android", "data", "com.nubia.gallery"});
                break;
            case BrandUtil.SHARP:
                brandGallery.add(new String[]{"Android", "data", "com.sharp.gallery"});
                break;
            case BrandUtil.LEPHONE:
                brandGallery.add(new String[]{"Android", "data", "com.letv.android.gallery3d"});
                break;
            case BrandUtil.HONOR:
                brandGallery.add(new String[]{"Huawei"});
                brandGallery.add(new String[]{"Android", "data", "com.huawei.himovie"});
                break;
        }
        return brandGallery;
    }

    public static List<String[]> getWeiXin() {
        return wxDirList;
    }

    public static List<String[]> getQQ() {
        return qqList;
    }

    private static List<String[]> getImageScanDirectory(@RefreshScanType int scanType) {
        switch (scanType) {
            case FileType.IMAGE_GALLERY:
                return getGallery();
            case FileType.IMAGE_WEIXIN:
                return getWeiXin();
            case FileType.IMAGE_QQ:
                return getQQ();
        }
        return null;
    }

    public static List<String[]> getPreScanImageRelatedDirectory() {
        List<String[]> preList = new ArrayList<>();
        preList.add(new String[]{"DCIM"});
        preList.add(new String[]{"Pictures"});
        preList.add(new String[]{"Download"});
        preList.add(new String[]{"Android", "data", "com.android.gallery3d"});
        preList.add(new String[]{"Android", "data", "com.android.gallery"});
        preList.addAll(FileScanHelper.getFactoryGalleryDir());
        preList.add(new String[]{"Android", "data", "com.tencent.mm"});
        preList.add(new String[]{"Android", "data", "com.tencent.mobileqq"});
        return preList;
    }

    public static List<String[]> getPreScanFileRelatedDirectory() {
        List<String[]> preList = new ArrayList<>();
        //文件保存相关路径
        preList.add(new String[]{"Download"});
        preList.add(new String[]{"DCIM"});
        preList.add(new String[]{"Browser"});
        preList.add(new String[]{"Movies"});
        preList.add(new String[]{"Music"});
        preList.add(new String[]{"QQBrowser"});
        preList.add(new String[]{"UCDownloads"});
        preList.add(new String[]{"BaiduNetdisk"});
        preList.add(new String[]{"Quark"});
        preList.add(new String[]{"Android", "data", "com.tencent.mm"});
        preList.add(new String[]{"Android", "data", "com.tencent.mobileqq"});
        return preList;
    }

    public static void searchExternalDirectory(Context context) {
    }


}
