package aicare.net.cn.sdk.ailinksdkdemoandroid.utils;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import androidx.annotation.NonNull;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;


/**
 * Abstract class that takes care of background threading the file log operation on Android.
 * implementing classes are free to directly perform I/O operations there.
 * <p>
 * Writes all logs to the disk with CSV format.
 */
public class MyDiskLogStrategy {

    @NonNull
    private final Handler handler;

    public MyDiskLogStrategy(@NonNull Handler handler) {
        this.handler = checkNotNull(handler);
    }

    public void log(@NonNull String message) {
        checkNotNull(message);
        handler.sendMessage(handler.obtainMessage(1, message));
    }

    /**
     * 保存缓存
     */
    public void saveCache() {
        //通知直接将缓存数据写入保存
        handler.sendMessage(handler.obtainMessage(2, "saveCache"));
    }

    static class WriteHandler extends Handler {

        @NonNull
        private final String folder;
        private final int maxFileSize;
        private final String fileName;
        private volatile List<String> mList;
        private final int mListMax;

        WriteHandler(@NonNull Looper looper, @NonNull String folder, String fileName, int maxFileSize,int listMax) {
            super(checkNotNull(looper));
            this.folder = checkNotNull(folder);
            this.maxFileSize = maxFileSize;
            this.fileName = fileName;
            mList=new ArrayList<>();
            mListMax=listMax;
        }

        @SuppressWarnings("checkstyle:emptyblock")
        @Override
        public void handleMessage(@NonNull Message msg) {

            if (msg.what==1) {
                //普通的保存数据,先判断缓存
                String content = (String) msg.obj;
                mList.add(content);
                if (mList.size()<mListMax){
                    return;
                }
            }

            FileWriter fileWriter = null;
            File logFile = getLogFile(folder, fileName);
            try {
                fileWriter = new FileWriter(logFile, true);
//                fileWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(logFile, true), StandardCharsets.UTF_8));
                writeLog(fileWriter, mList);
//                writeLog(fileWriter, content);
                fileWriter.flush();
                fileWriter.close();
            } catch (IOException e) {
                if (fileWriter != null) {
                    try {
                        fileWriter.flush();
                        fileWriter.close();
                    } catch (IOException e1) { /* fail silently */ }
                }
            }

        }
        private void writeLog(@NonNull OutputStreamWriter fileWriter, List<String> list) throws IOException {
            if (list!=null) {
                StringBuilder newStr= new StringBuilder();
                for (String s : list) {
                    newStr.append(s);
                }
                writeLog(fileWriter,newStr.toString());
                list.clear();
            }
        }

        /**
         * This is always called on a single background thread.
         * Implementing classes must ONLY write to the fileWriter and nothing more.
         * The abstract class takes care of everything else including close the stream and catching IOException
         *
         * @param fileWriter an instance of FileWriter already initialised to the correct file
         */
        private void writeLog(@NonNull OutputStreamWriter fileWriter, @NonNull String content) throws IOException {
            checkNotNull(fileWriter);
            checkNotNull(content);
            fileWriter.append(content);
        }

        private File getLogFile(@NonNull String folderName, @NonNull String fileName) {
            checkNotNull(folderName);
            checkNotNull(fileName);

            File folder = new File(folderName);
            if (!folder.exists()) {
                //TODO: What if folder is not created, what happens then?
                folder.mkdirs();
            }

            File newFile;
            newFile = new File(folder, fileName);

            if (newFile.exists()) {
                long length=newFile.length();
                if (length > maxFileSize) {
                    try {
                        byte[] fileByte=new byte[maxFileSize>>1];
                        RandomAccessFile randomAccessFileIn=new RandomAccessFile(newFile,"rw");
                        randomAccessFileIn.seek((length-fileByte.length));
                        randomAccessFileIn.read(fileByte);
                        randomAccessFileIn.close();
                        FileOutputStream fileOutputStream=new FileOutputStream(newFile);
                        fileOutputStream.write(fileByte);
                        fileOutputStream.flush();
                        fileOutputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            } else {
                try {
                    newFile.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return newFile;

        }
    }

    public static <T> T checkNotNull(T obj) {
        if (obj == null) {
            throw new NullPointerException();
        }
        return obj;
    }


}
