package com.yutou.okhttp;

import com.yutou.qqbot.interfaces.DownloadInterface;
import com.yutou.qqbot.utlis.ConfigTools;
import com.yutou.qqbot.utlis.Log;
import lombok.Data;
import okhttp3.*;
import org.jetbrains.annotations.NotNull;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

public class HttpDownloadUtils {
    public static void download(Builder builder) {
        createHttpClient(builder).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                if (builder.downloadInterface != null) {
                    builder.downloadInterface.onError(e);
                }
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                InputStream inputStream = Objects.requireNonNull(response.body()).byteStream();
                File target;
                if (StringUtils.hasText(builder.fileName)) {
                    target = new File(builder.path, builder.fileName);
                } else {
                    target = new File(builder.path);
                }
                FileOutputStream fileOutputStream = new FileOutputStream(target);
                if (builder.downloadInterface != null) {
                    builder.downloadInterface.onDownloadStart();
                }
                try {
                    byte[] buffer = new byte[2048];
                    int len;
                    long soFarBytes = 0;
                    long totalBytes = inputStream.available();
                    while ((len = inputStream.read(buffer)) != -1) {
                        fileOutputStream.write(buffer, 0, len);
                        soFarBytes += len;
                        if (builder.downloadInterface != null) {
                            if (!builder.downloadInterface.onDownloading(soFarBytes, totalBytes)) {
                                break;
                            }
                        }
                    }
                    fileOutputStream.flush();
                } catch (IOException e) {
                    Log.e(e,"download error:", builder.url);
                } finally {
                    if (builder.downloadInterface != null) {
                        builder.downloadInterface.onDownload(target);
                    }
                }

            }
        });
    }

    public static File downloadSync(Builder builder) {
        try {
            Response response = createHttpClient(builder).execute();
            InputStream inputStream = Objects.requireNonNull(response.body()).byteStream();
            File target;
            if (StringUtils.hasText(builder.fileName)) {
                target = new File(builder.path, builder.fileName);
            } else {
                target = new File(builder.path);
            }
            try (FileOutputStream fileOutputStream = new FileOutputStream(target)) {
                byte[] buffer = new byte[2048];
                int len;
                while ((len = inputStream.read(buffer)) != -1) {
                    fileOutputStream.write(buffer, 0, len);
                }
                fileOutputStream.flush();
                return target;
            } catch (IOException e) {
                Log.e(e,"download error:" , builder.url);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return null;
    }

    private static Call createHttpClient(Builder builder) {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(2, TimeUnit.MINUTES)
                .readTimeout(2, TimeUnit.MINUTES)
                .build();
        Request.Builder rb = new Request.Builder()
                .get()
                .addHeader("User-Agent", ConfigTools.getUserAgent())
                .url(builder.url);
        if (StringUtils.hasText(builder.cookie)) {
            rb.addHeader("Set-Cookie", builder.cookie);
            rb.addHeader("Cookie", builder.cookie);
        }
        Request request = rb.build();
        return okHttpClient.newCall(request);
    }

    @Data
    public static class Builder {
        String url;
        String path;
        String fileName;
        DownloadInterface downloadInterface;
        String cookie;

        public Builder setUrl(String url) {
            this.url = url;
            return this;
        }

        public Builder setPath(String path) {
            this.path = path;
            return this;
        }

        public Builder setFileName(String fileName) {
            this.fileName = fileName;
            return this;
        }

        public Builder setDownloadInterface(DownloadInterface downloadInterface) {
            this.downloadInterface = downloadInterface;
            return this;
        }

        public Builder setCookie(String cookie) {
            this.cookie = cookie;
            return this;
        }
    }
}
