package fi.nls.oskari.control.admin;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import fi.nls.oskari.annotation.OskariActionRoute;
import fi.nls.oskari.control.ActionDeniedException;
import fi.nls.oskari.control.ActionException;
import fi.nls.oskari.control.ActionParameters;
import fi.nls.oskari.control.ActionParamsException;
import fi.nls.oskari.service.ServiceException;
import fi.nls.oskari.service.ServiceUnauthorizedException;
import fi.nls.oskari.util.PropertyUtil;
import fi.nls.oskari.util.ResponseHelper;
import org.oskari.admin.LayerCapabilitiesHelper;
import org.oskari.maplayer.model.ServiceCapabilitiesResult;

import javax.servlet.http.HttpServletResponse;
import java.net.MalformedURLException;
import java.net.URL;

@OskariActionRoute("ServiceCapabilities")
public class ServiceCapabilitiesHandler extends AbstractLayerAdminHandler {
    private static final String PARAM_CAPABILITIES_URL = "url";
    private static final String PARAM_CURRENT_SRS = "srs";
    private static final String PARAM_VERSION = "version";
    private static final String PARAM_USERNAME = "user";
    private static final String PARAM_PASSWORD = "pw";
    private static final String PARAM_TYPE = "type";
    private static final String ERROR_INVALID_FIELD_VALUE = "invalid_field_value";

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    static {
        OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }

    /**
     * Get layer for editing or list available layers for adding new layer
     *
     * Changes to LayerAdmin:
     * old -> this one
     * id (not sent) -> -1
     * is_base -> base_map
     * internal (not sent) -> boolean
     * parentid -1 -> (not sent)
     * capabilities_update_rate -> capabilities_update_rate_sec
     * dataprovider_id (not sent) -> 0
     *
     * @param params
     * @throws ActionException
     */
    @Override
    public void handleGet(ActionParameters params) throws ActionException {
        if (!userHasAddPermission(params.getUser())) {
            throw new ActionDeniedException("User doesn't have add layer permission");
        }
        //GetCapabilities
        try {
            ServiceCapabilitiesResult results = getLayersFromService(params);
            final String output = OBJECT_MAPPER.writeValueAsString(results);
            params.getResponse().setCharacterEncoding("UTF-8");
            params.getResponse().setContentType("application/json;charset=UTF-8");
            ResponseHelper.writeResponse(params, output);
        } catch (Exception e) {
            if (isServiceUnauthrorizedException(e)) {
                ResponseHelper.writeError(params, e.getMessage(), HttpServletResponse.SC_UNAUTHORIZED);
            } else {
                ResponseHelper.writeError(params, e.getMessage());
            }
        }
    }

    private ServiceCapabilitiesResult getLayersFromService(ActionParameters params) throws ServiceException, ActionException {
        final String url = validateUrl(params.getRequiredParam(PARAM_CAPABILITIES_URL));
        final String type = params.getRequiredParam(PARAM_TYPE);
        final String version = params.getRequiredParam(PARAM_VERSION);
        final String username = params.getHttpParam(PARAM_USERNAME, "");
        final String password = params.getHttpParam(PARAM_PASSWORD, "");
        final String currentSrs = params.getHttpParam(PARAM_CURRENT_SRS, PropertyUtil.get("oskari.native.srs", "EPSG:4326"));
        return LayerCapabilitiesHelper.getCapabilitiesResults(url, type, version, username, password, currentSrs);
    }

    private String validateUrl(final String url) throws ActionParamsException {
        // TODO remove query part with ? check or with URL object
        String baseUrl = url.contains("?") ? url.substring(0, url.indexOf("?")) : url;
        baseUrl = baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl;
        try {
            // check that it's a valid url by creating an URL object...
            new URL(url);
        } catch (MalformedURLException e) {
            throw new ActionParamsException("Invalid url: " + url, ERROR_INVALID_FIELD_VALUE);
        }
        return baseUrl;
    }

    private boolean isServiceUnauthrorizedException(Throwable t) {
        return getRootCause(t) instanceof ServiceUnauthorizedException;
    }

    private Throwable getRootCause(Throwable e) {
        if (e == null) {
            return null;
        }
        Throwable cause = e.getCause();
        if (e == cause || cause == null) {
            return e;
        }
        return getRootCause(cause);
    }
}

@@ -613,32 +613,81 @@
 bilitiesHelper;%0A
+import org.oskari.maplayer.admin.LayerValidator;%0A
 import org.oskar
@@ -3104,16 +3104,31 @@
 g url = 
+LayerValidator.
 validate
@@ -3177,24 +3177,24 @@
 TIES_URL));%0A
-
         fina
@@ -3585,24 +3585,24 @@
 SG:4326%22));%0A
+
         retu
@@ -3715,629 +3715,8 @@
  %7D%0A%0A
-    private String validateUrl(final String url) throws ActionParamsException %7B%0A        // TODO remove query part with ? check or with URL object%0A        String baseUrl = url.contains(%22?%22) ? url.substring(0, url.indexOf(%22?%22)) : url;%0A        baseUrl = baseUrl.endsWith(%22/%22) ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl;%0A        try %7B%0A            // check that it's a valid url by creating an URL object...%0A            new URL(url);%0A        %7D catch (MalformedURLException e) %7B%0A            throw new ActionParamsException(%22Invalid url: %22 + url, ERROR_INVALID_FIELD_VALUE);%0A        %7D%0A        return baseUrl;%0A    %7D%0A%0A
     

Use layervalidator to validate url instead of removing querystring