package org.jboss.resteasy.test.resource.param.resource;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.CookieParam;
import jakarta.ws.rs.FormParam;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.HeaderParam;
import jakarta.ws.rs.MatrixParam;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;

public class MultiValuedParamResource {

    @Path("queryParam")
    public static class QueryParamResource {

        // http://xxx/queryParam/customConversion_multiValuedParam?date=20161217,20161218,20161219
        @GET
        @Path("customConversion_multiValuedParam")
        public Response customConversion_multiValuedParam(@QueryParam("date") MultiValuedParam<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // http://xxx/queryParam/customConversion_multiValuedParam_array?date=20161217,20161218,20161219
        @GET
        @Path("customConversion_multiValuedParam_array")
        public Response customConversion_multiValuedParam_array(@QueryParam("date") ParamWrapper<Date>[] dates) {
            Collection<Date> dateCollection = new ArrayList<>();
            for (ParamWrapper<Date> paramWrapper : dates) {
                dateCollection.add(paramWrapper.getElement());
            }
            return Response.ok(formatDates(dateCollection)).build();
        }

        // http://xxx/queryParam/defaultConversion_list?date=20161217&date=20161218&date=20161219
        @GET
        @Path("defaultConversion_list")
        public Response defaultConversion_list(@QueryParam("date") List<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // http://xxx/queryParam/defaultConversion_arrayList?date=20161217&date=20161218&date=20161219
        @GET
        @Path("defaultConversion_arrayList")
        public Response defaultConversion_arrayList(@QueryParam("date") ArrayList<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // http://xxx/queryParam/defaultConversion_set?date=20161217&date=20161218&date=20161219
        @GET
        @Path("defaultConversion_set")
        public Response defaultConversion_set(@QueryParam("date") Set<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // http://xxx/queryParam/defaultConversion_hashSet?date=20161217&date=20161218&date=20161219
        @GET
        @Path("defaultConversion_hashSet")
        public Response defaultConversion_hashSet(@QueryParam("date") HashSet<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // http://xxx/queryParam/defaultConversion_sortedSet?date=20161217&date=20161218&date=20161219
        @GET
        @Path("defaultConversion_sortedSet")
        public Response defaultConversion_sortedSet(@QueryParam("date") SortedSet<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // http://xxx/queryParam/defaultConversion_treeSet?date=20161217&date=20161218&date=20161219
        @GET
        @Path("defaultConversion_treeSet")
        public Response defaultConversion_treeSet(@QueryParam("date") TreeSet<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // http://xxx/queryParam/defaultConversion_array?date=20161217&date=20161218&date=20161219
        @GET
        @Path("defaultConversion_array")
        public Response defaultConversion_array(@QueryParam("date") Date[] dates) {
            return Response.ok(formatDates(Arrays.asList(dates))).build();
        }

    }

    @Path("headerParam")
    public static class HeaderParamResource {

        // date:20161217,20161218,20161219
        @GET
        @Path("customConversion_multiValuedParam")
        public Response customConversion_multiValuedParam(@HeaderParam("date") MultiValuedParam<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // date:20161217,20161218,20161219
        @GET
        @Path("customConversion_multiValuedParam_array")
        public Response customConversion_multiValuedParam_array(@HeaderParam("date") ParamWrapper<Date>[] dates) {
            Collection<Date> dateCollection = new ArrayList<>();
            for (ParamWrapper<Date> paramWrapper : dates) {
                dateCollection.add(paramWrapper.getElement());
            }
            return Response.ok(formatDates(dateCollection)).build();
        }

        // date:20161217,20161218,20161219
        @GET
        @Path("defaultConversion_list")
        public Response defaultConversion_list(@HeaderParam("date") List<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // date:20161217,20161218,20161219
        @GET
        @Path("defaultConversion_arrayList")
        public Response defaultConversion_arrayList(@HeaderParam("date") ArrayList<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // date:20161217,20161218,20161219
        @GET
        @Path("defaultConversion_set")
        public Response defaultConversion_set(@HeaderParam("date") Set<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // date:20161217,20161218,20161219
        @GET
        @Path("defaultConversion_hashSet")
        public Response defaultConversion_hashSet(@HeaderParam("date") HashSet<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // date:20161217,20161218,20161219
        @GET
        @Path("defaultConversion_sortedSet")
        public Response defaultConversion_sortedSet(@HeaderParam("date") SortedSet<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // date:20161217,20161218,20161219
        @GET
        @Path("defaultConversion_treeSet")
        public Response defaultConversion_treeSet(@HeaderParam("date") TreeSet<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // date:20161217,20161218,20161219
        @GET
        @Path("defaultConversion_array")
        public Response defaultConversion_array(@HeaderParam("date") Date[] dates) {
            return Response.ok(formatDates(Arrays.asList(dates))).build();
        }

    }

    @Path("matrixParam")
    public static class MatrixParamResource {

        // http://xxx/matrixParam/customConversion_multiValuedParam;date=20161217,20161218,20161219
        @GET
        @Path("customConversion_multiValuedParam")
        public Response customConversion_multiValuedParam(@MatrixParam("date") MultiValuedParam<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // http://xxx/matrixParam/customConversion_multiValuedParam_array;date=20161217,20161218,20161219
        @GET
        @Path("customConversion_multiValuedParam_array")
        public Response customConversion_multiValuedParam_array(@MatrixParam("date") ParamWrapper<Date>[] dates) {
            Collection<Date> dateCollection = new ArrayList<>();
            for (ParamWrapper<Date> paramWrapper : dates) {
                dateCollection.add(paramWrapper.getElement());
            }
            return Response.ok(formatDates(dateCollection)).build();
        }

        // http://xxx/matrixParam/defaultConversion_list;date=20161217;date=20161218;date=20161219
        @GET
        @Path("defaultConversion_list")
        public Response defaultConversion_list(@MatrixParam("date") List<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // http://xxx/matrixParam/defaultConversion_arrayList;date=20161217;date=20161218;date=20161219
        @GET
        @Path("defaultConversion_arrayList")
        public Response defaultConversion_arrayList(@MatrixParam("date") ArrayList<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // http://xxx/matrixParam/defaultConversion_set;date=20161217;date=20161218;date=20161219
        @GET
        @Path("defaultConversion_set")
        public Response defaultConversion_set(@MatrixParam("date") Set<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // http://xxx/matrixParam/defaultConversion_hashSet;date=20161217;date=20161218;date=20161219
        @GET
        @Path("defaultConversion_hashSet")
        public Response defaultConversion_hashSet(@MatrixParam("date") HashSet<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // http://xxx/matrixParam/defaultConversion_sortedSet;date=20161217;date=20161218;date=20161219
        @GET
        @Path("defaultConversion_sortedSet")
        public Response defaultConversion_sortedSet(@MatrixParam("date") SortedSet<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // http://xxx/matrixParam/defaultConversion_treeSet;date=20161217;date=20161218;date=20161219
        @GET
        @Path("defaultConversion_treeSet")
        public Response defaultConversion_treeSet(@MatrixParam("date") TreeSet<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // http://xxx/matrixParam/defaultConversion_array;date=20161217;date=20161218;date=20161219
        @GET
        @Path("defaultConversion_array")
        public Response defaultConversion_array(@MatrixParam("date") Date[] dates) {
            return Response.ok(formatDates(Arrays.asList(dates))).build();
        }

    }

    @Path("cookieParam")
    public static class CookieParamResource {

        // cookie:date=20161217-20161218-20161219
        @GET
        @Path("customConversion_multiValuedCookieParam")
        public Response customConversion_multiValuedCookieParam(@CookieParam("date") MultiValuedCookieParam<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // cookie:date=20161217-20161218-20161219
        @GET
        @Path("customConversion_multiValuedCookieParam_array")
        public Response customConversion_multiValuedCookieParam_array(@CookieParam("date") CookieParamWrapper<Date>[] dates) {
            Collection<Date> dateCollection = new ArrayList<>();
            for (CookieParamWrapper<Date> paramWrapper : dates) {
                dateCollection.add(paramWrapper.getElement());
            }
            return Response.ok(formatDates(dateCollection)).build();
        }

        // cookie:date=20161217
        @GET
        @Path("defaultConversion_list")
        public Response defaultConversion_list(@CookieParam("date") List<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // cookie:date=20161217
        @GET
        @Path("defaultConversion_arrayList")
        public Response defaultConversion_arrayList(@CookieParam("date") ArrayList<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // cookie:date=20161217
        @GET
        @Path("defaultConversion_set")
        public Response defaultConversion_set(@CookieParam("date") Set<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // cookie:date=20161217
        @GET
        @Path("defaultConversion_hashSet")
        public Response defaultConversion_hashSet(@CookieParam("date") HashSet<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // cookie:date=20161217
        @GET
        @Path("defaultConversion_sortedSet")
        public Response defaultConversion_sortedSet(@CookieParam("date") SortedSet<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // cookie:date=20161217
        @GET
        @Path("defaultConversion_treeSet")
        public Response defaultConversion_treeSet(@CookieParam("date") TreeSet<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // cookie:date=20161217
        @GET
        @Path("defaultConversion_array")
        public Response defaultConversion_array(@CookieParam("date") Date[] dates) {
            return Response.ok(formatDates(Arrays.asList(dates))).build();
        }

    }

    @Path("formParam")
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public static class FormParamResource {

        // date=20161217,20161218,20161219
        @POST
        @Path("customConversion_multiValuedParam")
        public Response customConversion_multiValuedParam(@FormParam("date") MultiValuedParam<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // date=20161217,20161218,20161219
        @POST
        @Path("customConversion_multiValuedParam_array")
        public Response customConversion_multiValuedParam_array(@FormParam("date") ParamWrapper<Date>[] dates) {
            Collection<Date> dateCollection = new ArrayList<>();
            for (ParamWrapper<Date> paramWrapper : dates) {
                dateCollection.add(paramWrapper.getElement());
            }
            return Response.ok(formatDates(dateCollection)).build();
        }

        // date=20161217&date=20161218&date=20161219
        @POST
        @Path("defaultConversion_list")
        public Response defaultConversion_list(@FormParam("date") List<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // date=20161217&date=20161218&date=20161219
        @POST
        @Path("defaultConversion_arrayList")
        public Response defaultConversion_arrayList(@FormParam("date") ArrayList<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // date=20161217&date=20161218&date=20161219
        @POST
        @Path("defaultConversion_set")
        public Response defaultConversion_set(@FormParam("date") Set<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // date=20161217&date=20161218&date=20161219
        @POST
        @Path("defaultConversion_hashSet")
        public Response defaultConversion_hashSet(@FormParam("date") HashSet<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // date=20161217&date=20161218&date=20161219
        @POST
        @Path("defaultConversion_sortedSet")
        public Response defaultConversion_sortedSet(@FormParam("date") SortedSet<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // date=20161217&date=20161218&date=20161219
        @POST
        @Path("defaultConversion_treeSet")
        public Response defaultConversion_treeSet(@FormParam("date") TreeSet<Date> dates) {
            return Response.ok(formatDates(dates)).build();
        }

        // date=20161217&date=20161218&date=20161219
        @POST
        @Path("defaultConversion_array")
        public Response defaultConversion_array(@FormParam("date") Date[] dates) {
            return Response.ok(formatDates(Arrays.asList(dates))).build();
        }

    }

    @Path("pathParam")
    public static class PathParamResource {

        // http://xxx/pathParam/customConversion_multiValuedPathParam/20161217/20161218/20161219
        @GET
        @Path("customConversion_multiValuedPathParam/{path: .+}")
        public Response customConversion_multiValuedPathParam(@PathParam("path") MultiValuedPathParam<Date> paths) {
            return Response.ok(formatDates(paths)).build();
        }

        // http://xxx/pathParam/customConversion_multiValuedPathParam_array/20161217/20161218/20161219
        @GET
        @Path("customConversion_multiValuedPathParam_array/{path: .+}")
        public Response customConversion_multiValuedPathParam_array(@PathParam("path") PathParamWrapper<Date>[] paths) {
            Collection<Date> pathCollection = new ArrayList<>();
            for (PathParamWrapper<Date> paramWrapper : paths) {
                pathCollection.add(paramWrapper.getElement());
            }
            return Response.ok(formatDates(pathCollection)).build();
        }

        // http://xxx/pathParam/defaultConversion_list/20161217
        @GET
        @Path("defaultConversion_list/{path: .+}")
        public Response defaultConversion_list(@PathParam("path") List<Date> paths) {
            return Response.ok(formatDates(paths)).build();
        }

        // http://xxx/pathParam/defaultConversion_arrayList/20161217
        @GET
        @Path("defaultConversion_arrayList/{path: .+}")
        public Response defaultConversion_arrayList(@PathParam("path") ArrayList<Date> paths) {
            return Response.ok(formatDates(paths)).build();
        }

        // http://xxx/pathParam/defaultConversion_set/20161217
        @GET
        @Path("defaultConversion_set/{path: .+}")
        public Response defaultConversion_set(@PathParam("path") Set<Date> paths) {
            return Response.ok(formatDates(paths)).build();
        }

        // http://xxx/pathParam/defaultConversion_hashSet/20161217
        @GET
        @Path("defaultConversion_hashSet/{path: .+}")
        public Response defaultConversion_hashSet(@PathParam("path") HashSet<Date> paths) {
            return Response.ok(formatDates(paths)).build();
        }

        // http://xxx/pathParam/defaultConversion_sortedSet/20161217
        @GET
        @Path("defaultConversion_sortedSet/{path: .+}")
        public Response defaultConversion_sortedSet(@PathParam("path") SortedSet<Date> paths) {
            return Response.ok(formatDates(paths)).build();
        }

        // http://xxx/pathParam/defaultConversion_treeSet/20161217
        @GET
        @Path("defaultConversion_treeSet/{path: .+}")
        public Response defaultConversion_treeSet(@PathParam("path") TreeSet<Date> paths) {
            return Response.ok(formatDates(paths)).build();
        }

        // http://xxx/pathParam/defaultConversion_array/20161217
        @GET
        @Path("defaultConversion_array/{path: .+}")
        public Response defaultConversion_array(@PathParam("path") Date[] paths) {
            return Response.ok(formatDates(Arrays.asList(paths))).build();
        }

    }

    private static String formatDates(Collection<Date> dates) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
        StringBuilder stringBuilder = new StringBuilder();
        int datesCount = dates.size();
        int i = 0;
        for (Date date : new TreeSet<>(dates)) {
            stringBuilder.append(simpleDateFormat.format(date));
            ++i;
            if (i < datesCount) {
                stringBuilder.append(",");
            }
        }
        return stringBuilder.toString();
    }

}
