/*
 * 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.foundation.vertx.http;

import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import javax.servlet.AsyncContext;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.Part;
import javax.ws.rs.core.HttpHeaders;

import org.apache.servicecomb.foundation.common.http.HttpUtils;
import org.apache.servicecomb.foundation.vertx.stream.BufferInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.vertx.core.MultiMap;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.net.SocketAddress;
import io.vertx.ext.web.FileUpload;
import io.vertx.ext.web.RoutingContext;

// wrap vertx http request to Servlet http request
public class VertxServerRequestToHttpServletRequest extends AbstractHttpServletRequest {
  private static final Logger LOGGER = LoggerFactory.getLogger(VertxServerRequestToHttpServletRequest.class);

  private static final EmptyAsyncContext EMPTY_ASYNC_CONTEXT = new EmptyAsyncContext();

  private final RoutingContext context;

  private final HttpServerRequest vertxRequest;

  private Cookie[] cookies;

  private ServletInputStream inputStream;

  private String path;

  private final SocketAddress socketAddress;

  // cache from convert vertx parameters to servlet parameters
  private Map<String, String[]> parameterMap;

  private String characterEncoding;

  public VertxServerRequestToHttpServletRequest(RoutingContext context, String path) {
    this(context);
    this.path = path;
  }

  public VertxServerRequestToHttpServletRequest(RoutingContext context) {
    this.context = context;
    this.vertxRequest = context.request();
    this.socketAddress = this.vertxRequest.remoteAddress();
    super.setBodyBuffer(context.getBody());
  }

  @Override
  public void setBodyBuffer(Buffer bodyBuffer) {
    super.setBodyBuffer(bodyBuffer);
    context.setBody(bodyBuffer);
    this.inputStream = null;
  }

  @Override
  public String getContentType() {
    return this.vertxRequest.getHeader(HttpHeaders.CONTENT_TYPE);
  }

  @Override
  public Cookie[] getCookies() {
    if (cookies == null) {
      Set<io.vertx.core.http.Cookie> cookieSet = context.request().cookies();
      Cookie[] tmpCookies = new Cookie[cookieSet.size()];
      int idx = 0;
      for (io.vertx.core.http.Cookie vertxCookie : cookieSet) {
        Cookie cookie = new Cookie(vertxCookie.getName(), vertxCookie.getValue());
        tmpCookies[idx] = cookie;
        idx++;
      }
      cookies = tmpCookies;
    }
    return cookies;
  }

  @Override
  public String getParameter(String name) {
    if (parameterMap != null) {
      String[] values = parameterMap.get(name);
      return values == null ? null : values[0];
    }

    return this.vertxRequest.getParam(name);
  }

  @Override
  public Enumeration<String> getParameterNames() {
    if (parameterMap != null) {
      return Collections.enumeration(parameterMap.keySet());
    }

    return Collections.enumeration(this.vertxRequest.params().names());
  }

  @Override
  public String[] getParameterValues(String name) {
    if (parameterMap != null) {
      return parameterMap.get(name);
    }

    List<String> paramList = this.vertxRequest.params().getAll(name);
    return paramList.toArray(new String[0]);
  }

  @Override
  public Map<String, String[]> getParameterMap() {
    if (parameterMap == null) {
      Map<String, String[]> paramMap = new HashMap<>();
      MultiMap map = this.vertxRequest.params();
      for (String name : map.names()) {
        List<String> valueList = map.getAll(name);
        paramMap.put(name, map.getAll(name).toArray(new String[valueList.size()]));
      }
      parameterMap = paramMap;
    }

    return parameterMap;
  }

  @Override
  public void setParameter(String name, String value) {
    if (parameterMap != null) {
      parameterMap.put(name, new String[] {value});
      return;
    }

    vertxRequest.params().set(name, value);
  }

  @Override
  public String getScheme() {
    return this.vertxRequest.scheme();
  }

  @Override
  public String getRemoteAddr() {
    return this.socketAddress.host();
  }

  @Override
  public String getRemoteHost() {
    return this.socketAddress.host();
  }

  @Override
  public int getRemotePort() {
    return this.socketAddress.port();
  }

  @Override
  public String getLocalAddr() {
    return this.vertxRequest.localAddress().host();
  }

  @Override
  public int getLocalPort() {
    return this.vertxRequest.localAddress().port();
  }

  @Override
  public String getHeader(String name) {
    return this.vertxRequest.getHeader(name);
  }

  @Override
  public Enumeration<String> getHeaders(String name) {
    return Collections.enumeration(this.vertxRequest.headers().getAll(name));
  }

  @Override
  public Enumeration<String> getHeaderNames() {
    return Collections.enumeration(vertxRequest.headers().names());
  }

  @Override
  public int getIntHeader(String name) {
    String header = this.vertxRequest.getHeader(name);
    if (header == null) {
      return -1;
    }

    return Integer.parseInt(header);
  }

  @Override
  public String getMethod() {
    return this.vertxRequest.method().name();
  }

  @Override
  public String getPathInfo() {
    return this.vertxRequest.path();
  }

  @Override
  public String getQueryString() {
    return this.vertxRequest.query();
  }

  @Override
  public String getRequestURI() {
    if (this.path == null) {
      this.path = vertxRequest.path();
    }
    return this.path;
  }

  @Override
  public String getServletPath() {
    return this.getPathInfo();
  }

  @Override
  public String getContextPath() {
    return "";
  }

  @Override
  public ServletInputStream getInputStream() {
    if (inputStream != null) {
      return inputStream;
    }
    if (context.getBody() == null) {
      return null;
    }
    inputStream = new BufferInputStream(context.getBody().getByteBuf());
    return inputStream;
  }

  @Override
  public AsyncContext getAsyncContext() {
    return EMPTY_ASYNC_CONTEXT;
  }

  @Override
  public Part getPart(String name) {
    Optional<FileUpload> upload = context.fileUploads()
        .stream()
        .filter(fileUpload -> fileUpload.name().equals(name))
        .findFirst();
    if (!upload.isPresent()) {
      LOGGER.debug("No such file with name: {}.", name);
      return null;
    }

    final FileUpload fileUpload = upload.get();
    return new FileUploadPart(fileUpload);
  }

  @Override
  public Collection<Part> getParts() {
    Set<FileUpload> fileUploads = context.fileUploads();
    return fileUploads.stream().map(FileUploadPart::new).collect(Collectors.toList());
  }

  public RoutingContext getContext() {
    return context;
  }

  @Override
  public String getCharacterEncoding() {
    if (characterEncoding == null) {
      characterEncoding = HttpUtils.getCharsetFromContentType(getContentType());
    }

    return characterEncoding;
  }
}
