/*
 * Copyright 2017 the original author or authors.
 *
 * Licensed 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 com.visionarts.powerjambda.models;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import com.visionarts.powerjambda.AwsProxyRequest;

/**
 * The request to populate an action.
 *
 * @param <T> The type of body in an action request
 *
 */
public class ActionRequest<T> {

    private AwsProxyRequest request;
    private Map<String, String> pathParameters;
    private Map<String, String> queryParameters;
    private T body;

    public ActionRequest() {
        this(null);
    }

    public ActionRequest(AwsProxyRequest request) {
        this.request = request;
        Optional.ofNullable(request).ifPresent(req -> {
            pathParameters = toUrlDecodedMap(req.getPathParameters());
            queryParameters = toUrlDecodedMap(req.getQueryStringParameters());
        });
    }

    /**
     * Returns HTTP method.
     *
     * @return HTTP method
     */
    public String getMethod() {
        return request.getHttpMethod();
    }

    /**
     * Returns remote IP address.
     *
     * @return Remote IP address
     */
    public String getRemoteAddr() {
        return request.getRequestContext().getIdentity().getSourceIp();
    }

    /**
     * Returns the name of deployment stage on API Gateway.
     *
     * @return The name of stage
     */
    public String getStage() {
        return request.getRequestContext().getStage();
    }

    public String getPath() {
        return request.getPath();
    }

    public Map<String, String> getHeaders() {
        return request.getHeaders();
    }

    public String getHeader(String key) {
        return request.getHeaders().get(key);
    }

    public Map<String, String> getPathParameters() {
        return pathParameters;
    }

    public String getPathParameter(String key) {
        return pathParameters.get(key);
    }

    public Map<String, String> getQueryParameters() {
        return queryParameters;
    }

    public String getQueryParameter(String key) {
        return queryParameters.get(key);
    }

    public T getBody() {
        return body;
    }

    public void setBody(T body) {
        this.body = body;
    }

    public String getBodyAsString() {
        return request.getBody();
    }

    private Map<String, String> toUrlDecodedMap(Map<String, String> src) {
        return Optional.ofNullable(src)
                .map(m -> m.entrySet().stream()
                    .collect(Collectors.toMap(e -> urlDecode(e.getKey()), e -> urlDecode(e.getValue()))))
                .orElseGet(() -> Collections.emptyMap());
    }

    private String urlDecode(String src) {
        try {
            return URLDecoder.decode(src, StandardCharsets.UTF_8.name());
        } catch (UnsupportedEncodingException e) { // never happen
            throw new RuntimeException(e);
        }
    }

}

@@ -668,224 +668,16 @@
 ava.
-io.UnsupportedEncodingException;%0Aimport java.net.URLDecoder;%0Aimport java.nio.charset.StandardCharsets;%0Aimport java.util.Collections;%0Aimport java.util.Map;%0Aimport java.util.Optional;%0Aimport java.util.stream.Collectors
+util.Map
 ;%0A%0Ai
@@ -905,105 +905,8 @@
 st;%0A
-    private Map%3CString, String%3E pathParameters;%0A    private Map%3CString, String%3E queryParameters;%0A
     
@@ -1066,226 +1066,8 @@
 st;%0A
-        Optional.ofNullable(request).ifPresent(req -%3E %7B%0A            pathParameters = toUrlDecodedMap(req.getPathParameters());%0A            queryParameters = toUrlDecodedMap(req.getQueryStringParameters());%0A        %7D);%0A
     
@@ -1956,33 +1956,44 @@
 %0A        return 
-p
+request.getP
 athParameters;%0A 
@@ -1981,32 +1981,34 @@
 etPathParameters
+()
 ;%0A    %7D%0A%0A    pub
@@ -2064,17 +2064,28 @@
  return 
-p
+request.getP
 athParam
@@ -2081,32 +2081,34 @@
 etPathParameters
+()
 .get(key);%0A    %7D
@@ -2170,37 +2170,54 @@
 %0A        return 
+re
 que
-ry
+st.getQueryString
 Parameters;%0A    
@@ -2210,16 +2210,18 @@
 rameters
+()
 ;%0A    %7D%0A
@@ -2290,13 +2290,30 @@
 urn 
+re
 que
-ry
+st.getQueryString
 Para
@@ -2318,16 +2318,18 @@
 rameters
+()
 .get(key
@@ -2534,605 +2534,12 @@
 ();%0A
+
     %7D%0A
-%0A    private Map%3CString, String%3E toUrlDecodedMap(Map%3CString, String%3E src) %7B%0A        return Optional.ofNullable(src)%0A                .map(m -%3E m.entrySet().stream()%0A                    .collect(Collectors.toMap(e -%3E urlDecode(e.getKey()), e -%3E urlDecode(e.getValue()))))%0A                .orElseGet(() -%3E Collections.emptyMap());%0A    %7D%0A%0A    private String urlDecode(String src) %7B%0A        try %7B%0A            return URLDecoder.decode(src, StandardCharsets.UTF_8.name());%0A        %7D catch (UnsupportedEncodingException e) %7B // never happen%0A            throw new RuntimeException(e);%0A        %7D%0A    %7D%0A%0A
 %7D%0A

Remove redundant URL encode process