package com.xunmei.common.core.http.service.params;

import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.Request;
import okhttp3.RequestBody;
import okio.BufferedSink;
import okio.Okio;
import okio.Source;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;


public class HttpParamsPostFile extends HttpParams {

    private static final MediaType MEDIA_TYPE_FILE = MediaType.parse("application/oct-stream");

    /**
     * @param mediaType
     * @param inputStream
     * @return
     */
    private static RequestBody create(final MediaType mediaType, final InputStream inputStream) {
        return new RequestBody() {
            @Override
            public MediaType contentType() {
                return mediaType;
            }

            @Override
            public long contentLength() {
                try {
                    return inputStream.available();
                } catch (final IOException e) {
                    return 0;
                }
            }

            @Override
            public void writeTo(final BufferedSink sink) throws IOException {
                Source source = null;
                try {
                    source = Okio.source(inputStream);
                    sink.writeAll(source);
                } finally {
                }
            }
        };
    }


    private final Map<String, Object> params;

    public HttpParamsPostFile(final String url, final Map<String, Object> params) {
        this.setUrl(url);
        this.params = Optional.ofNullable(params)
                              .orElse(Collections.emptyMap());
    }

    @Override
    protected Request.Builder toBuild() {
        final MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
        this.params.forEach((k, v) -> {
            if (v == null) {
                return;
            }
            if (v instanceof File) {
                final File f = (File) v;
                builder.addFormDataPart(
                        k, f.getName(), RequestBody.create(MEDIA_TYPE_FILE, f)
                );
            } else if (v instanceof InputStream) {
                builder.addFormDataPart(
                        k, k, create(MEDIA_TYPE_FILE, (InputStream) v)
                );
            } else if (v instanceof HttpMulitiParam) {
                final HttpMulitiParam p = (HttpMulitiParam) v;
                builder.addFormDataPart(
                        k, p.getFileName(), create(p.getMediaType(), p.getInputStream())
                );
            }
            //
            else {
                builder.addFormDataPart(k, v.toString());
            }
        });
        return new Request.Builder().url(this.getUrl())
                                    .post(builder.build());
    }

    @Override
    public HttpParams put(final String key, final Object page) {
        this.params.put(key, page);
        return this;
    }

}
