/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.servicecomb.common.rest.codec.param;

import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE;
import static javax.ws.rs.core.MediaType.MULTIPART_FORM_DATA;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;

import javax.servlet.http.Part;
import javax.ws.rs.core.MediaType;

import com.google.common.annotations.VisibleForTesting;
import org.apache.servicecomb.common.rest.codec.RestClientRequest;
import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
import org.apache.servicecomb.foundation.common.utils.PartUtils;
import org.apache.servicecomb.foundation.vertx.stream.BufferInputStream;
import org.apache.servicecomb.foundation.vertx.stream.BufferOutputStream;
import org.apache.servicecomb.foundation.vertx.stream.InputStreamToReadStream;
import org.apache.servicecomb.foundation.vertx.stream.PumpFromPart;
import org.apache.servicecomb.swagger.invocation.AsyncResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;

import io.vertx.core.Context;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.MultiMap;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpClientRequest;
import io.vertx.core.http.HttpHeaders;

public class RestClientRequestImpl implements RestClientRequest {
  private static final Logger LOGGER = LoggerFactory.getLogger(RestClientRequestImpl.class);

  protected Context context;

  protected AsyncResponse asyncResp;

  @VisibleForTesting
  final Multimap<String, Part> uploads = ArrayListMultimap.create();

  protected HttpClientRequest request;

  protected Map<String, String> cookieMap;

  protected Map<String, Object> formMap;

  protected Buffer bodyBuffer;

  private final Handler<Throwable> throwableHandler;

  public RestClientRequestImpl(HttpClientRequest request, Context context, AsyncResponse asyncResp) {
    this(request, context, asyncResp, null);
  }

  public RestClientRequestImpl(HttpClientRequest request, Context context, AsyncResponse asyncResp,
      Handler<Throwable> throwableHandler) {
    this.context = context;
    this.asyncResp = asyncResp;
    this.request = request;
    this.throwableHandler = throwableHandler;
  }

  @Override
  public void write(Buffer bodyBuffer) {
    this.bodyBuffer = bodyBuffer;
  }

  @Override
  public Buffer getBodyBuffer() throws Exception {
    genBodyBuffer();
    return bodyBuffer;
  }

  @Override
  @SuppressWarnings("unchecked")
  public void attach(String name, Object partOrList) {
    if (null == partOrList) {
      LOGGER.debug("null file is ignored, file name = [{}]", name);
      return;
    }

    if (partOrList.getClass().isArray()) {
      for (Object part : (Object[]) partOrList) {
        uploads.put(name, PartUtils.getSinglePart(name, part));
      }
    }

    if (List.class.isAssignableFrom(partOrList.getClass())) {
      for (Object part : (List<Object>) partOrList) {
        uploads.put(name, PartUtils.getSinglePart(name, part));
      }
      return;
    }

    uploads.put(name, PartUtils.getSinglePart(name, partOrList));
  }

  @Override
  public Future<Void> end() {
    writeCookies();

    if (!uploads.isEmpty()) {
      return doEndWithUpload();
    }

    return doEndNormal();
  }

  protected Future<Void> doEndWithUpload() {
    request.setChunked(true);

    String boundary = "boundary" + UUID.randomUUID();
    putHeader(CONTENT_TYPE, MULTIPART_FORM_DATA + "; charset=UTF-8; boundary=" + boundary);

    return genBodyForm(boundary).onSuccess(v -> attachFiles(boundary)).onFailure(e -> asyncResp.consumerFail(e));
  }

  private Future<Void> genBodyForm(String boundary) {
    if (formMap == null) {
      return Future.succeededFuture();
    }

    try {
      try (BufferOutputStream output = new BufferOutputStream()) {
        for (Entry<String, Object> entry : formMap.entrySet()) {
          output.write(bytesOf("\r\n"));
          output.write(bytesOf("--" + boundary + "\r\n"));
          output.write(bytesOf("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"\r\n\r\n"));
          if (entry.getValue() != null) {
            String value = RestObjectMapperFactory.getRestObjectMapper().convertToString(entry.getValue());
            output.write(value.getBytes(StandardCharsets.UTF_8));
          }
        }

        return writeBuffer(output.getBuffer());
      }
    } catch (Exception e) {
      return Future.failedFuture(e);
    }
  }

  private byte[] bytesOf(String string) {
    return string.getBytes(StandardCharsets.UTF_8);
  }

  protected Future<Void> doEndNormal() {
    try {
      genBodyBuffer();
    } catch (Exception e) {
      asyncResp.consumerFail(e);
      return Future.succeededFuture();
    }

    if (bodyBuffer == null) {
      return request.end();
    }

    return request.end(bodyBuffer);
  }

  private void attachFiles(String boundary) {
    Iterator<Entry<String, Part>> uploadsIterator = uploads.entries().iterator();
    attachFile(boundary, uploadsIterator);
  }

  private void attachFile(String boundary, Iterator<Entry<String, Part>> uploadsIterator) {
    if (!uploadsIterator.hasNext()) {
      writeBuffer(boundaryEndInfo(boundary)).onSuccess(v -> request.end()).onFailure(e -> asyncResp.consumerFail(e));
      return;
    }

    Entry<String, Part> entry = uploadsIterator.next();
    // do not use part.getName() to get parameter name
    // because pojo consumer not easy to set name to part
    String name = entry.getKey();
    Part part = entry.getValue();
    String filename = part.getSubmittedFileName();

    LOGGER.debug("Start attach file [{}:{}].", name, filename);
    writeBuffer(fileBoundaryInfo(boundary, name, part)).onSuccess(r ->
        new PumpFromPart(context, part).toWriteStream(request, throwableHandler).whenComplete((v, e) -> {
          if (e != null) {
            LOGGER.warn("Failed attach file [{}:{}].", name, filename, e);
            asyncResp.consumerFail(e);
            return;
          }

          LOGGER.debug("Finish attach file [{}:{}].", name, filename);
          attachFile(boundary, uploadsIterator);
        })).onFailure(e -> asyncResp.consumerFail(e));
  }

  private Buffer boundaryEndInfo(String boundary) {
    return Buffer.buffer()
        .appendString("\r\n")
        .appendString("--" + boundary + "--\r\n");
  }

  protected Buffer fileBoundaryInfo(String boundary, String name, Part part) {
    Buffer buffer = Buffer.buffer();
    buffer.appendString("\r\n");
    buffer.appendString("--" + boundary + "\r\n");
    buffer.appendString("Content-Disposition: form-data; name=\"")
        .appendString(name)
        .appendString("\"; filename=\"")
        .appendString(part.getSubmittedFileName() != null ? part.getSubmittedFileName() : "null")
        .appendString("\"\r\n");
    buffer.appendString("Content-Type: ").appendString(part.getContentType()).appendString("\r\n");
    buffer.appendString("Content-Transfer-Encoding: binary\r\n");
    buffer.appendString("\r\n");
    return buffer;
  }

  protected Future<Void> writeBuffer(Buffer buffer) {
    return new InputStreamToReadStream(context,
        new BufferInputStream(buffer.getByteBuf()), true).pipe().endOnComplete(false).to(request);
  }

  private void genBodyBuffer() throws Exception {
    if (bodyBuffer != null) {
      return;
    }

    if (formMap == null) {
      return;
    }

    request.putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED);
    try (BufferOutputStream output = new BufferOutputStream()) {
      for (Entry<String, Object> entry : formMap.entrySet()) {
        output.write(entry.getKey().getBytes(StandardCharsets.UTF_8));
        output.write('=');
        if (entry.getValue() != null) {
          String value = RestObjectMapperFactory.getRestObjectMapper().convertToString(entry.getValue());
          value = URLEncoder.encode(value, StandardCharsets.UTF_8.name());
          output.write(value.getBytes(StandardCharsets.UTF_8));
        }
        output.write('&');
      }
      bodyBuffer = output.getBuffer();
    }
  }

  private void writeCookies() {
    if (cookieMap == null) {
      return;
    }

    StringBuilder builder = new StringBuilder();
    for (Entry<String, String> entry : cookieMap.entrySet()) {
      builder.append(entry.getKey())
          .append('=')
          .append(entry.getValue())
          .append("; ");
    }
    request.putHeader(HttpHeaders.COOKIE, builder.toString());
  }

  public Context getContext() {
    return context;
  }

  public HttpClientRequest getRequest() {
    return request;
  }

  public Map<String, String> getCookieMap() {
    return cookieMap;
  }

  @Override
  public void addCookie(String name, String value) {
    if (cookieMap == null) {
      cookieMap = new HashMap<>();
    }

    cookieMap.put(name, value);
  }

  @Override
  public void addForm(String name, Object value) {
    if (formMap == null) {
      formMap = new HashMap<>();
    }

    if (value != null) {
      formMap.put(name, value);
    }
  }

  @Override
  public void putHeader(String name, String value) {
    request.putHeader(name, value);
  }

  @Override
  public MultiMap getHeaders() {
    return request.headers();
  }
}
