/*
 * Copyright 2019 slavb.
 *
 * 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 ru.ilb.common.openapi.generator;

import io.swagger.v3.core.filter.OpenAPISpecFilter;
import io.swagger.v3.core.model.ApiDescription;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.media.MediaType;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.parameters.RequestBody;
import io.swagger.v3.oas.models.responses.ApiResponse;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author slavb
 */
public class OpenAPISpecFilterImpl implements OpenAPISpecFilter {

    static final Logger LOG = Logger.getLogger(OpenAPISpecFilterImpl.class.getName());

    @Override
    public Optional<OpenAPI> filterOpenAPI(OpenAPI openAPI, Map<String, List<String>> params, Map<String, String> cookies, Map<String, List<String>> headers) {
        return Optional.of(openAPI);
    }

    @Override
    public Optional<PathItem> filterPathItem(PathItem pathItem, ApiDescription api, Map<String, List<String>> params, Map<String, String> cookies, Map<String, List<String>> headers) {
        return Optional.of(pathItem);
    }

    @Override
    public Optional<Operation> filterOperation(Operation operation, ApiDescription api, Map<String, List<String>> params, Map<String, String> cookies, Map<String, List<String>> headers) {
        return Optional.of(operation);
    }

    @Override
    public Optional<Parameter> filterParameter(Parameter parameter, Operation operation, ApiDescription api, Map<String, List<String>> params, Map<String, String> cookies, Map<String, List<String>> headers) {
        return Optional.of(parameter);
    }

    @Override
    public Optional<RequestBody> filterRequestBody(RequestBody requestBody, Operation operation, ApiDescription api, Map<String, List<String>> params, Map<String, String> cookies, Map<String, List<String>> headers) {
        //skip CXF MultipartBody schema generation
        MediaType mt = requestBody.getContent().get("multipart/form-data");
        if (mt != null && mt.getSchema() != null && mt.getSchema().get$ref() != null && mt.getSchema().get$ref().contains("MultipartBody")) {
            mt.getSchema().setType("object");
            mt.getSchema().set$ref(null);
            LOG.log(Level.INFO, () -> "filterRequestBody operationId=" + operation.getOperationId() + " replace MultipartBody with object");
        }
        return Optional.of(requestBody);
    }

    @Override
    public Optional<ApiResponse> filterResponse(ApiResponse response, Operation operation, ApiDescription api, Map<String, List<String>> params, Map<String, String> cookies, Map<String, List<String>> headers) {
        return Optional.of(response);
    }

    @Override
    public Optional<Schema> filterSchema(Schema schema, Map<String, List<String>> params, Map<String, String> cookies, Map<String, List<String>> headers) {
        return Optional.of(schema);
    }

    @Override
    public Optional<Schema> filterSchemaProperty(Schema property, Schema schema, String propName, Map<String, List<String>> params, Map<String, String> cookies, Map<String, List<String>> headers) {
        return Optional.of(property);
    }

    @Override
    public boolean isRemovingUnreferencedDefinitions() {
        return true;
    }

}

@@ -852,16 +852,67 @@
 thItem;%0A
+import io.swagger.v3.oas.models.media.ArraySchema;%0A
 import i
@@ -1163,16 +1163,41 @@
 sponse;%0A
+import java.util.Arrays;%0A
 import j
@@ -2732,12 +2732,15 @@
   //
-skip
+replace
  CXF
@@ -2758,25 +2758,24 @@
 ody 
-schema generation
+with file upload
 %0A   
@@ -3005,81 +3005,488 @@
     
-mt.getSchema().setType(%22object%22);%0A            mt.getSchema().set$ref(null
+Schema schema = mt.getSchema();%0A            schema.setType(%22object%22);%0A            schema.set$ref(null);%0A            // @see https://swagger.io/docs/specification/describing-request-body/file-upload/%0A            // single file upload%0A            schema.addProperties(%22file%22, new Schema().type(%22string%22).format(%22binary%22));%0A            // multi file upload%0A            //schema.addProperties(%22file%22, new ArraySchema().type(%22array%22).items(new Schema().type(%22string%22).format(%22binary%22))
 );%0A 

replace CXF MultipartBody with file upload