/*
 * 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.logging.log4j.layout.template.json.util;

import org.apache.logging.log4j.util.Strings;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Callable;

public final class StringParameterParser {

    private StringParameterParser() {}

    public static final class Values {

        private Values() {}

        static NullValue nullValue() {
            return NullValue.INSTANCE;
        }

        static StringValue stringValue(final String string) {
            return new StringValue(string);
        }

        static DoubleQuotedStringValue doubleQuotedStringValue(
                final String doubleQuotedString) {
            return new DoubleQuotedStringValue(doubleQuotedString);
        }

    }

    public interface Value {}

    public static final class NullValue implements Value {

        private static final NullValue INSTANCE = new NullValue();

        private NullValue() {}

        @Override
        public String toString() {
            return "null";
        }

    }

    public static final class StringValue implements Value {

        private final String string;

        private StringValue(final String string) {
            this.string = string;
        }

        public String getString() {
            return string;
        }

        @Override
        public boolean equals(final Object object) {
            if (this == object) {
                return true;
            }
            if (object == null || getClass() != object.getClass()) {
                return false;
            }
            final StringValue that = (StringValue) object;
            return string.equals(that.string);
        }

        @Override
        public int hashCode() {
            return 31 + Objects.hashCode(string);
        }

        @Override
        public String toString() {
            return string;
        }

    }

    public static final class DoubleQuotedStringValue implements Value {

        private final String doubleQuotedString;

        private DoubleQuotedStringValue(final String doubleQuotedString) {
            this.doubleQuotedString = doubleQuotedString;
        }

        public String getDoubleQuotedString() {
            return doubleQuotedString;
        }

        @Override
        public boolean equals(final Object object) {
            if (this == object) {
                return true;
            }
            if (object == null || getClass() != object.getClass()) {
                return false;
            }
            final DoubleQuotedStringValue that = (DoubleQuotedStringValue) object;
            return doubleQuotedString.equals(that.doubleQuotedString);
        }

        @Override
        public int hashCode() {
            return 31 + Objects.hashCode(doubleQuotedString);
        }

        @Override
        public String toString() {
            return doubleQuotedString.replaceAll("\\\\\"", "\"");
        }

    }

    private enum State { READING_KEY, READING_VALUE }

    private static final class Parser implements Callable<Map<String, Value>> {

        private final String input;

        private final Map<String, Value> map;

        private State state;

        private int i;

        private String key;

        private Parser(final String input) {
            this.input = Objects.requireNonNull(input, "input");
            this.map = new LinkedHashMap<>();
            this.state = State.READING_KEY;
            this.i = 0;
            this.key = null;
        }

        @Override
        public Map<String, Value> call() {
            while (true) {
                skipWhitespace();
                if (i >= input.length()) {
                    break;
                }
                switch (state) {
                    case READING_KEY:
                        readKey();
                        break;
                    case READING_VALUE:
                        readValue();
                        break;
                    default:
                        throw new IllegalStateException("unknown state: " + state);
                }
            }
            if (state == State.READING_VALUE) {
                map.put(key, Values.nullValue());
            }
            return map;
        }

        private void readKey() {
            final int eq = input.indexOf('=', i);
            final int co = input.indexOf(',', i);
            final int j;
            final int nextI;
            if (eq < 0 && co < 0) {
                // Neither '=', nor ',' was found.
                j = nextI = input.length();
            } else if (eq < 0) {
                // Found ','.
                j = nextI = co;
            } else if (co < 0) {
                // Found '='.
                j = eq;
                nextI = eq + 1;
            } else if (eq < co) {
                // Found '=...,'.
                j = eq;
                nextI = eq + 1;
            } else {
                // Found ',...='.
                j = co;
                nextI = co;
            }
            key = input.substring(i, j).trim();
            if (Strings.isEmpty(key)) {
                final String message = String.format(
                        "failed to locate key at index %d: %s",
                        i, input);
                throw new IllegalArgumentException(message);
            }
            if (map.containsKey(key)) {
                final String message = String.format(
                        "conflicting key at index %d: %s",
                        i, input);
                throw new IllegalArgumentException(message);
            }
            state = State.READING_VALUE;
            i = nextI;
        }

        private void readValue() {
            final boolean doubleQuoted = input.charAt(i) == '"';
            if (doubleQuoted) {
                readDoubleQuotedStringValue();
            } else {
                readStringValue();
            }
            key = null;
            state = State.READING_KEY;
        }

        private void readDoubleQuotedStringValue() {
            int j = i + 1;
            while (j < input.length()) {
                if (input.charAt(j) == '"' && input.charAt(j - 1) != '\\') {
                    break;
                } else {
                    j++;
                }
            }
            if (j >= input.length()) {
                final String message = String.format(
                        "failed to locate the end of double-quoted content starting at index %d: %s",
                        i, input);
                throw new IllegalArgumentException(message);
            }
            final String content = input
                    .substring(i + 1, j)
                    .replaceAll("\\\\\"", "\"");
            final Value value = Values.doubleQuotedStringValue(content);
            map.put(key, value);
            i = j + 1;
            skipWhitespace();
            if (i < input.length()) {
                if (input.charAt(i) != ',') {
                    final String message = String.format(
                            "was expecting comma at index %d: %s",
                            i, input);
                    throw new IllegalArgumentException(message);
                }
                i++;
            }
        }

        private void skipWhitespace() {
            while (i < input.length()) {
                final char c = input.charAt(i);
                if (!Character.isWhitespace(c)) {
                    break;
                } else {
                    i++;
                }
            }
        }

        private void readStringValue() {
            int j = input.indexOf(',', i/* + 1*/);
            if (j < 0) {
                j = input.length();
            }
            final String content = input.substring(i, j);
            final String trimmedContent = content.trim();
            final Value value = trimmedContent.isEmpty()
                    ? Values.nullValue()
                    : Values.stringValue(trimmedContent);
            map.put(key, value);
            i += content.length() + 1;
        }

    }

    public static Map<String, Value> parse(final String input) {
        return parse(input, null);
    }

    public static Map<String, Value> parse(
            final String input,
            final Set<String> allowedKeys) {
        if (Strings.isBlank(input)) {
            return Collections.emptyMap();
        }
        final Map<String, Value> map = new Parser(input).call();
        final Set<String> actualKeys = map.keySet();
        for (final String actualKey : actualKeys) {
            final boolean allowed = allowedKeys == null || allowedKeys.contains(actualKey);
            if (!allowed) {
                final String message = String.format(
                        "unknown key \"%s\" is found in input: %s",
                        actualKey, input);
                throw new IllegalArgumentException(message);
            }
        }
        return map;
    }

}
