/*
 * 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.kafka.message;

import java.io.BufferedWriter;
import java.io.IOException;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;

public final class ApiMessageTypeGenerator {
    private final HeaderGenerator headerGenerator;
    private final CodeBuffer buffer;
    private final TreeMap<Short, ApiData> apis;

    private static final class ApiData {
        short apiKey;
        MessageSpec requestSpec;
        MessageSpec responseSpec;

        ApiData(short apiKey) {
            this.apiKey = apiKey;
        }

        String name() {
            if (requestSpec != null) {
                return MessageGenerator.stripSuffix(requestSpec.name(),
                    MessageGenerator.REQUEST_SUFFIX);
            } else if (responseSpec != null) {
                return MessageGenerator.stripSuffix(responseSpec.name(),
                    MessageGenerator.RESPONSE_SUFFIX);
            } else {
                throw new RuntimeException("Neither requestSpec nor responseSpec is defined " +
                    "for API key " + apiKey);
            }
        }

        String requestSchema() {
            if (requestSpec == null) {
                return "null";
            } else {
                return String.format("%sData.SCHEMAS", requestSpec.name());
            }
        }

        String responseSchema() {
            if (responseSpec == null) {
                return "null";
            } else {
                return String.format("%sData.SCHEMAS", responseSpec.name());
            }
        }
    }

    public ApiMessageTypeGenerator() {
        this.headerGenerator = new HeaderGenerator();
        this.apis = new TreeMap<>();
        this.buffer = new CodeBuffer();
    }

    public void registerMessageType(MessageSpec spec) {
        switch (spec.type()) {
            case REQUEST: {
                short apiKey = spec.apiKey().get();
                ApiData data = apis.get(apiKey);
                if (!apis.containsKey(apiKey)) {
                    data = new ApiData(apiKey);
                    apis.put(apiKey, data);
                }
                if (data.requestSpec != null) {
                    throw new RuntimeException("Found more than one request with " +
                        "API key " + spec.apiKey().get());
                }
                data.requestSpec = spec;
                break;
            }
            case RESPONSE: {
                short apiKey = spec.apiKey().get();
                ApiData data = apis.get(apiKey);
                if (!apis.containsKey(apiKey)) {
                    data = new ApiData(apiKey);
                    apis.put(apiKey, data);
                }
                if (data.responseSpec != null) {
                    throw new RuntimeException("Found more than one response with " +
                        "API key " + spec.apiKey().get());
                }
                data.responseSpec = spec;
                break;
            }
            default:
                // do nothing
                break;
        }
    }

    public void generate() {
        buffer.printf("public enum ApiMessageType {%n");
        buffer.incrementIndent();
        generateEnumValues();
        buffer.printf("%n");
        generateInstanceVariables();
        buffer.printf("%n");
        generateEnumConstructor();
        buffer.printf("%n");
        generateFromApiKey();
        buffer.printf("%n");
        generateNewApiMessageMethod("request");
        buffer.printf("%n");
        generateNewApiMessageMethod("response");
        buffer.printf("%n");
        generateAccessor("apiKey", "short");
        buffer.printf("%n");
        generateAccessor("requestSchemas", "Schema[]");
        buffer.printf("%n");
        generateAccessor("responseSchemas", "Schema[]");
        buffer.printf("%n");
        generateToString();
        buffer.decrementIndent();
        buffer.printf("}%n");
        headerGenerator.generate();
    }

    private void generateEnumValues() {
        int numProcessed = 0;
        for (Map.Entry<Short, ApiData> entry : apis.entrySet()) {
            ApiData apiData = entry.getValue();
            String name = apiData.name();
            numProcessed++;
            buffer.printf("%s(\"%s\", (short) %d, %s, %s)%s%n",
                MessageGenerator.toSnakeCase(name).toUpperCase(Locale.ROOT),
                MessageGenerator.capitalizeFirst(name),
                entry.getKey(),
                apiData.requestSchema(),
                apiData.responseSchema(),
                (numProcessed == apis.size()) ? ";" : ",");
        }
    }

    private void generateInstanceVariables() {
        buffer.printf("private final String name;%n");
        buffer.printf("private final short apiKey;%n");
        buffer.printf("private final Schema[] requestSchemas;%n");
        buffer.printf("private final Schema[] responseSchemas;%n");
        headerGenerator.addImport(MessageGenerator.SCHEMA_CLASS);
    }

    private void generateEnumConstructor() {
        buffer.printf("ApiMessageType(String name, short apiKey, " +
            "Schema[] requestSchemas, Schema[] responseSchemas) {%n");
        buffer.incrementIndent();
        buffer.printf("this.name = name;%n");
        buffer.printf("this.apiKey = apiKey;%n");
        buffer.printf("this.requestSchemas = requestSchemas;%n");
        buffer.printf("this.responseSchemas = responseSchemas;%n");
        buffer.decrementIndent();
        buffer.printf("}%n");
    }

    private void generateFromApiKey() {
        buffer.printf("public static ApiMessageType fromApiKey(short apiKey) {%n");
        buffer.incrementIndent();
        buffer.printf("switch (apiKey) {%n");
        buffer.incrementIndent();
        for (Map.Entry<Short, ApiData> entry : apis.entrySet()) {
            ApiData apiData = entry.getValue();
            String name = apiData.name();
            buffer.printf("case %d:%n", entry.getKey());
            buffer.incrementIndent();
            buffer.printf("return %s;%n", MessageGenerator.toSnakeCase(name).toUpperCase(Locale.ROOT));
            buffer.decrementIndent();
        }
        buffer.printf("default:%n");
        buffer.incrementIndent();
        headerGenerator.addImport(MessageGenerator.UNSUPPORTED_VERSION_EXCEPTION_CLASS);
        buffer.printf("throw new UnsupportedVersionException(\"Unsupported API key \"" +
            " + apiKey);%n");
        buffer.decrementIndent();
        buffer.decrementIndent();
        buffer.printf("}%n");
        buffer.decrementIndent();
        buffer.printf("}%n");
    }

    private void generateNewApiMessageMethod(String type) {
        headerGenerator.addImport(MessageGenerator.API_MESSAGE_CLASS);
        buffer.printf("public ApiMessage new%s() {%n",
            MessageGenerator.capitalizeFirst(type));
        buffer.incrementIndent();
        buffer.printf("switch (apiKey) {%n");
        buffer.incrementIndent();
        for (Map.Entry<Short, ApiData> entry : apis.entrySet()) {
            buffer.printf("case %d:%n", entry.getKey());
            buffer.incrementIndent();
            buffer.printf("return new %s%sData();%n",
                entry.getValue().name(),
                MessageGenerator.capitalizeFirst(type));
            buffer.decrementIndent();
        }
        buffer.printf("default:%n");
        buffer.incrementIndent();
        headerGenerator.addImport(MessageGenerator.UNSUPPORTED_VERSION_EXCEPTION_CLASS);
        buffer.printf("throw new UnsupportedVersionException(\"Unsupported %s API key \"" +
            " + apiKey);%n", type);
        buffer.decrementIndent();
        buffer.decrementIndent();
        buffer.printf("}%n");
        buffer.decrementIndent();
        buffer.printf("}%n");
    }

    private void generateAccessor(String name, String type) {
        buffer.printf("public %s %s() {%n", type, name);
        buffer.incrementIndent();
        buffer.printf("return this.%s;%n", name);
        buffer.decrementIndent();
        buffer.printf("}%n");
    }

    private void generateToString() {
        buffer.printf("@Override%n");
        buffer.printf("public String toString() {%n");
        buffer.incrementIndent();
        buffer.printf("return this.name();%n");
        buffer.decrementIndent();
        buffer.printf("}%n");
    }

    public void write(BufferedWriter writer) throws IOException {
        headerGenerator.buffer().write(writer);
        buffer.write(writer);
    }
}
