/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * 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 com.android.server.wifi.util;

import android.text.TextUtils;
import android.util.ArrayMap;

import java.io.PrintWriter;
import java.time.Duration;
import java.time.format.DateTimeParseException;

/**
 * Parses a list of key=value pairs, separated by some delimiter, and puts the results in
 * an internal Map. Values can be then queried by key, or if not found, a default value
 * can be used.
 *
 * Note: @hide class copied from android.util (with ProtoStream dependency stripped out)
 */
public class KeyValueListParser {
    private final ArrayMap<String, String> mValues = new ArrayMap<>();
    private final TextUtils.StringSplitter mSplitter;

    /**
     * Constructs a new KeyValueListParser. This can be reused for different strings
     * by calling {@link #setString(String)}.
     * @param delim The delimiter that separates key=value pairs.
     */
    public KeyValueListParser(char delim) {
        mSplitter = new TextUtils.SimpleStringSplitter(delim);
    }

    /**
     * Resets the parser with a new string to parse. The string is expected to be in the following
     * format:
     * <pre>key1=value,key2=value,key3=value</pre>
     *
     * where the delimiter is a comma.
     *
     * @param str the string to parse.
     * @throws IllegalArgumentException if the string is malformed.
     */
    public void setString(String str) throws IllegalArgumentException {
        mValues.clear();
        if (str != null) {
            mSplitter.setString(str);
            for (String pair : mSplitter) {
                int sep = pair.indexOf('=');
                if (sep < 0) {
                    mValues.clear();
                    throw new IllegalArgumentException(
                            "'" + pair + "' in '" + str + "' is not a valid key-value pair");
                }
                mValues.put(pair.substring(0, sep).trim(), pair.substring(sep + 1).trim());
            }
        }
    }

    /**
     * Get the value for key as an int.
     * @param key The key to lookup.
     * @param def The value to return if the key was not found, or the value was not a long.
     * @return the int value associated with the key.
     */
    public int getInt(String key, int def) {
        String value = mValues.get(key);
        if (value != null) {
            try {
                return Integer.parseInt(value);
            } catch (NumberFormatException e) {
                // fallthrough
            }
        }
        return def;
    }

    /**
     * Get the value for key as a long.
     * @param key The key to lookup.
     * @param def The value to return if the key was not found, or the value was not a long.
     * @return the long value associated with the key.
     */
    public long getLong(String key, long def) {
        String value = mValues.get(key);
        if (value != null) {
            try {
                return Long.parseLong(value);
            } catch (NumberFormatException e) {
                // fallthrough
            }
        }
        return def;
    }

    /**
     * Get the value for key as a float.
     * @param key The key to lookup.
     * @param def The value to return if the key was not found, or the value was not a float.
     * @return the float value associated with the key.
     */
    public float getFloat(String key, float def) {
        String value = mValues.get(key);
        if (value != null) {
            try {
                return Float.parseFloat(value);
            } catch (NumberFormatException e) {
                // fallthrough
            }
        }
        return def;
    }

    /**
     * Get the value for key as a string.
     * @param key The key to lookup.
     * @param def The value to return if the key was not found.
     * @return the string value associated with the key.
     */
    public String getString(String key, String def) {
        String value = mValues.get(key);
        if (value != null) {
            return value;
        }
        return def;
    }

    /**
     * Get the value for key as a boolean.
     * @param key The key to lookup.
     * @param def The value to return if the key was not found.
     * @return the string value associated with the key.
     */
    public boolean getBoolean(String key, boolean def) {
        String value = mValues.get(key);
        if (value != null) {
            try {
                return Boolean.parseBoolean(value);
            } catch (NumberFormatException e) {
                // fallthrough
            }
        }
        return def;
    }

    /**
     * Get the value for key as an integer array.
     *
     * The value should be encoded as "0:1:2:3:4"
     *
     * @param key The key to lookup.
     * @param def The value to return if the key was not found.
     * @return the int[] value associated with the key.
     */
    public int[] getIntArray(String key, int[] def) {
        String value = mValues.get(key);
        if (value != null) {
            try {
                String[] parts = value.split(":");
                if (parts.length > 0) {
                    int[] ret = new int[parts.length];
                    for (int i = 0; i < parts.length; i++) {
                        ret[i] = Integer.parseInt(parts[i]);
                    }
                    return ret;
                }
            } catch (NumberFormatException e) {
                // fallthrough
            }
        }
        return def;
    }

    /**
     * @return the number of keys.
     */
    public int size() {
        return mValues.size();
    }

    /**
     * @return the key at {@code index}. Use with {@link #size()} to enumerate all key-value pairs.
     */
    public String keyAt(int index) {
        return mValues.keyAt(index);
    }

    /**
     * {@hide}
     * Parse a duration in millis based on java.time.Duration or just a number (millis)
     */
    public long getDurationMillis(String key, long def) {
        String value = mValues.get(key);
        if (value != null) {
            try {
                if (value.startsWith("P") || value.startsWith("p")) {
                    return Duration.parse(value).toMillis();
                } else {
                    return Long.parseLong(value);
                }
            } catch (NumberFormatException | DateTimeParseException e) {
                // fallthrough
            }
        }
        return def;
    }

    /** Represents an integer config value. */
    public static class IntValue {
        private final String mKey;
        private final int mDefaultValue;
        private int mValue;

        /** Constructor, initialize with a config key and a default value. */
        public IntValue(String key, int defaultValue) {
            mKey = key;
            mDefaultValue = defaultValue;
            mValue = mDefaultValue;
        }

        /** Read a value from {@link KeyValueListParser} */
        public void parse(KeyValueListParser parser) {
            mValue = parser.getInt(mKey, mDefaultValue);
        }

        /** Return the config key. */
        public String getKey() {
            return mKey;
        }

        /** Return the default value. */
        public int getDefaultValue() {
            return mDefaultValue;
        }

        /** Return the actual config value. */
        public int getValue() {
            return mValue;
        }

        /** Overwrites with a value. */
        public void setValue(int value) {
            mValue = value;
        }

        /** Used for dumpsys */
        public void dump(PrintWriter pw, String prefix) {
            pw.print(prefix);
            pw.print(mKey);
            pw.print("=");
            pw.print(mValue);
            pw.println();
        }
    }

    /** Represents an long config value. */
    public static class LongValue {
        private final String mKey;
        private final long mDefaultValue;
        private long mValue;

        /** Constructor, initialize with a config key and a default value. */
        public LongValue(String key, long defaultValue) {
            mKey = key;
            mDefaultValue = defaultValue;
            mValue = mDefaultValue;
        }

        /** Read a value from {@link KeyValueListParser} */
        public void parse(KeyValueListParser parser) {
            mValue = parser.getLong(mKey, mDefaultValue);
        }

        /** Return the config key. */
        public String getKey() {
            return mKey;
        }

        /** Return the default value. */
        public long getDefaultValue() {
            return mDefaultValue;
        }

        /** Return the actual config value. */
        public long getValue() {
            return mValue;
        }

        /** Overwrites with a value. */
        public void setValue(long value) {
            mValue = value;
        }

        /** Used for dumpsys */
        public void dump(PrintWriter pw, String prefix) {
            pw.print(prefix);
            pw.print(mKey);
            pw.print("=");
            pw.print(mValue);
            pw.println();
        }
    }

    /** Represents an string config value. */
    public static class StringValue {
        private final String mKey;
        private final String mDefaultValue;
        private String mValue;

        /** Constructor, initialize with a config key and a default value. */
        public StringValue(String key, String defaultValue) {
            mKey = key;
            mDefaultValue = defaultValue;
            mValue = mDefaultValue;
        }

        /** Read a value from {@link KeyValueListParser} */
        public void parse(KeyValueListParser parser) {
            mValue = parser.getString(mKey, mDefaultValue);
        }

        /** Return the config key. */
        public String getKey() {
            return mKey;
        }

        /** Return the default value. */
        public String getDefaultValue() {
            return mDefaultValue;
        }

        /** Return the actual config value. */
        public String getValue() {
            return mValue;
        }

        /** Overwrites with a value. */
        public void setValue(String value) {
            mValue = value;
        }

        /** Used for dumpsys */
        public void dump(PrintWriter pw, String prefix) {
            pw.print(prefix);
            pw.print(mKey);
            pw.print("=");
            pw.print(mValue);
            pw.println();
        }
    }

    /** Represents an float config value. */
    public static class FloatValue {
        private final String mKey;
        private final float mDefaultValue;
        private float mValue;

        /** Constructor, initialize with a config key and a default value. */
        public FloatValue(String key, float defaultValue) {
            mKey = key;
            mDefaultValue = defaultValue;
            mValue = mDefaultValue;
        }

        /** Read a value from {@link KeyValueListParser} */
        public void parse(KeyValueListParser parser) {
            mValue = parser.getFloat(mKey, mDefaultValue);
        }

        /** Return the config key. */
        public String getKey() {
            return mKey;
        }

        /** Return the default value. */
        public float getDefaultValue() {
            return mDefaultValue;
        }

        /** Return the actual config value. */
        public float getValue() {
            return mValue;
        }

        /** Overwrites with a value. */
        public void setValue(float value) {
            mValue = value;
        }

        /** Used for dumpsys */
        public void dump(PrintWriter pw, String prefix) {
            pw.print(prefix);
            pw.print(mKey);
            pw.print("=");
            pw.print(mValue);
            pw.println();
        }
    }
}
