package com.xhly.corelib.utils;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Comparator;

/**
 * Created by YQ015 on 2018/4/12.
 */

public class FileUtils {

    private static FileUtils instance;
    private static final int SUCCESS = 1;
    private static final int FAILED = 0;
    private Context context;
    private FileOperateCallback callback;
    private volatile boolean isSuccess;
    private String errorStr;

    public static FileUtils getInstance(Context context) {
        if (instance == null)
            instance = new FileUtils(context);
        return instance;
    }

    public static FileUtils getInstance() {
        if (instance == null)
            instance = new FileUtils();
        return instance;
    }

    private FileUtils() {
    }

    private FileUtils(Context context) {
        this.context = context;
    }

    private Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (callback != null) {
                if (msg.what == SUCCESS) {
                    callback.onSuccess();
                }
                if (msg.what == FAILED) {
                    callback.onFailed(msg.obj.toString());
                }
            }
        }
    };


    public static void moveFile(String fromFile, String toFile) {
        //安卓9.0多出两个缓存文件wal和shm
        File fromfile = new File(fromFile);
        File tofile = new File(toFile);
        if (!tofile.exists()) {
            try {
                if (tofile.isDirectory()) {
                    tofile.mkdir();
                } else {
                    tofile.createNewFile();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        CopyFile(fromfile.toString(), tofile.toString());
        if (fromfile.exists()) {
            fromfile.delete();
        }
    }

    public FileUtils copyAssetsToSD(final String srcPath, final String sdPath) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                copyAssetsToDst(context, srcPath, sdPath);
                Log.d(this.getClass().getName(),"失败没有="+isSuccess);
                if (isSuccess)
                    handler.obtainMessage(SUCCESS).sendToTarget();
                else
                    handler.obtainMessage(FAILED, errorStr).sendToTarget();
            }
        }).start();
        return this;
    }

    public static void CopyDir(String sourcePath, String newPath) throws IOException {
        File file = new File(sourcePath);
        String[] filePath = file.list();

        if (!(new File(newPath)).exists()) {
            (new File(newPath)).mkdir();
        }

        for (int i = 0; i < filePath.length; i++) {
            if ((new File(sourcePath + file.separator + filePath[i])).isDirectory()) {
                CopyDir(sourcePath + file.separator + filePath[i], newPath + file.separator + filePath[i]);
            }

            if (new File(sourcePath + file.separator + filePath[i]).isFile()) {
                CopyFile(sourcePath + file.separator + filePath[i], newPath + file.separator + filePath[i]);
            }

        }
    }

    public static int CopyFile(String fromFile, String toFile) {
        try {
            InputStream fosfrom = new FileInputStream(fromFile);
            OutputStream fosto = new FileOutputStream(toFile);
            byte bt[] = new byte[1024];
            int c;
            while ((c = fosfrom.read(bt)) > 0) {
                fosto.write(bt, 0, c);
            }
            fosfrom.close();
            fosto.close();
            return 0;

        } catch (Exception ex) {
            return -1;
        }
    }

    public static int saveInputStreamFile(InputStream fosfrom, String toFile) {
        try {
            OutputStream fosto = new FileOutputStream(toFile);
            byte bt[] = new byte[1024];
            int c;
            while ((c = fosfrom.read(bt)) > 0) {
                fosto.write(bt, 0, c);
            }
            fosfrom.close();
            fosto.close();
            return 0;

        } catch (Exception ex) {
            return -1;
        }
    }

    /**
     * 删除目录下的文件，不涉及下一级目录，不删除目录本身
     * @param file 目录
     * @return 0成功
     */
    public static int deleteCurrentFlie(File file) {
        try {
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                for (int i = 0; i < files.length; i++) {
                    files[i].delete();
                }
            }
            return 0;
        } catch (Exception ex) {
            return -1;
        }
    }

    //删除目录下的文件，只保留最新1条，不涉及下一级目录，不删除目录本身
    public static int deleteOnlyOneFlie(File file) {
        try {
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                // 根据文件的最后修改时间进行排序
                Arrays.sort(files, Comparator.comparingLong(File::lastModified).reversed());
                // 保留最新文件的数量
                int keepCount = 1;
                for (int i = keepCount; i < files.length; i++) {
                    files[i].delete();
                }
            }
            return 0;
        } catch (Exception ex) {
            return -1;
        }
    }

    public static boolean deleteFile(String fileName) {
        File file = new File(fileName);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * 删除目录及目录下的文件
     *
     * @param dir 要删除的目录的文件路径
     * @return 目录删除成功返回true，否则返回false
     */
    public static boolean deleteDirectory(String dir) {
        // 如果dir不以文件分隔符结尾，自动添加文件分隔符
        if (!dir.endsWith(File.separator))
            dir = dir + File.separator;
        File dirFile = new File(dir);
        // 如果dir对应的文件不存在，或者不是一个目录，则退出
        if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
            return false;
        }
        boolean flag = true;
        // 删除文件夹中的所有文件包括子目录
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            // 删除子文件
            if (files[i].isFile()) {
                flag = FileUtils.deleteFile(files[i].getAbsolutePath());
                if (!flag)
                    break;
            }
            // 删除子目录
            else if (files[i].isDirectory()) {
                flag = FileUtils.deleteDirectory(files[i]
                        .getAbsolutePath());
                if (!flag)
                    break;
            }
        }
        if (!flag) {
            return false;
        }
        // 删除当前目录
        if (dirFile.toString().equals(dir.toString())) {
            return true;
        } else {
            if (dirFile.delete()) {
                return true;
            } else {
                return false;
            }
        }
    }

    public void setFileOperateCallback(FileOperateCallback callback) {
        this.callback = callback;
    }

    private void copyAssetsToDst(Context context, String srcPath, String dstPath) {
        try {
            File outFile = new File(dstPath);
            if (!outFile.exists()) {
                outFile.createNewFile();
                InputStream is = context.getAssets().open(srcPath);
                FileOutputStream fos = new FileOutputStream(outFile);
                byte[] buffer = new byte[1024];
                int byteCount;
                while ((byteCount = is.read(buffer)) != -1) {
                    fos.write(buffer, 0, byteCount);
                }
                fos.flush();
                is.close();
                fos.close();
            }
            isSuccess = true;
        } catch (Exception e) {
            e.printStackTrace();
            errorStr = e.getMessage();
            isSuccess = false;
            Log.d(this.getClass().getName(),"失败"+e.toString());
        }
    }

    public byte[] getAssetsRes(Context context, String srcPath) {
        try {
            InputStream is = context.getAssets().open(srcPath);
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            int n = 0;
            while (-1 != (n = is.read(buffer))) {
                output.write(buffer, 0, n);
            }
            byte[] bytes = output.toByteArray();
            return bytes;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    public String getAssetsResource(Context context, String srcPath) {
        try {
            InputStream is = context.getAssets().open(srcPath);
            InputStreamReader inputStreamReader = null;
            inputStreamReader = new InputStreamReader(is, "UTF-8");
            BufferedReader reader = new BufferedReader(inputStreamReader);
            StringBuffer sb = new StringBuffer("");
            String line;
            while ((line = reader.readLine()) != null) {
                //添加到字符缓冲流中
                sb.append(line);
                sb.append("\n");
            }
            return sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    public void writeFileData(String filename, String content, Context context) {
        //写入文件到File目录下
        try {
            FileOutputStream fos = context.openFileOutput(filename, context.MODE_PRIVATE);//获得FileOutputStream
            //将要写入的字符串转换为byte数组
            byte[] bytes = content.getBytes();
            fos.write(bytes);//将byte数组写入文件
            fos.close();//关闭文件输出流

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void writeFileToPath(String filename, String content) {
        //写入文件到自定义目录下
        try {
            FileOutputStream fos = new FileOutputStream(filename);
            //将要写入的字符串转换为byte数组
            byte[] bytes = content.getBytes();
            fos.write(bytes);//将byte数组写入文件
            fos.close();//关闭文件输出流

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void writeFileToPath(String filename, byte[] bytes) {
        //写入文件到自定义目录下
        try {
            FileOutputStream fos = new FileOutputStream(filename);
            //将要写入的字符串转换为byte数组
            fos.write(bytes);//将byte数组写入文件
            fos.close();//关闭文件输出流

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String readFileToPath(String filename) {
        //读取自定义目录下文件
        try {
            FileInputStream is = new FileInputStream(filename);
            InputStreamReader inputStreamReader = null;
            inputStreamReader = new InputStreamReader(is, "UTF-8");
            BufferedReader reader = new BufferedReader(inputStreamReader);
            StringBuffer sb = new StringBuffer("");
            String line;
            while ((line = reader.readLine()) != null) {
                //添加到字符缓冲流中
                sb.append(line);
                sb.append("\n");
            }
            return sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    public interface FileOperateCallback {
        void onSuccess();

        void onFailed(String error);
    }
}
