/*
 * Copyright (C) 2018 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.
 */

#include <unistd.h>
#include <string>

#include <android-base/file.h>
#include <android-base/test_utils.h>
#include <gtest/gtest.h>

#include "JavaGen.h"

namespace {

constexpr const char* kTestSyspropFile =
    R"(owner: Vendor
module: "com.somecompany.TestProperties"

prop {
    api_name: "test_double"
    type: Double
    prop_name: "vendor.test_double"
    scope: Internal
    access: ReadWrite
}
prop {
    api_name: "test_int"
    type: Integer
    prop_name: "vendor.test_int"
    scope: Public
    access: ReadWrite
}
prop {
    api_name: "test_string"
    type: String
    prop_name: "vendor.test.string"
    scope: Public
    access: Readonly
    legacy_prop_name: "vendor.old.string"
}
prop {
    api_name: "test_enum"
    type: Enum
    prop_name: "vendor.test.enum"
    enum_values: "a|b|c|D|e|f|G"
    scope: Internal
    access: ReadWrite
}
prop {
    api_name: "test_BOOLeaN"
    type: Boolean
    prop_name: "ro.vendor.test.b"
    scope: Public
    access: Writeonce
}
prop {
    api_name: "vendor_os_test-long"
    type: Long
    scope: Public
    access: ReadWrite
}
prop {
    api_name: "test_double_list"
    type: DoubleList
    scope: Internal
    access: ReadWrite
}
prop {
    api_name: "test_list_int"
    type: IntegerList
    scope: Public
    access: ReadWrite
}
prop {
    api_name: "test_strlist"
    type: StringList
    scope: Public
    access: ReadWrite
    deprecated: true
}
prop {
    api_name: "el"
    type: EnumList
    enum_values: "enu|mva|lue"
    scope: Internal
    access: ReadWrite
    deprecated: true
}
)";

constexpr const char* kExpectedPublicOutput =
    R"s(// Generated by the sysprop generator. DO NOT EDIT!

package com.somecompany;

import android.os.SystemProperties;
import android.util.Log;

import java.lang.StringBuilder;
import java.util.ArrayList;
import java.util.function.Function;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.StringJoiner;
import java.util.stream.Collectors;

public final class TestProperties {
    private TestProperties () {}

    private static Boolean tryParseBoolean(String str) {
        if (str == null) return null;
        switch (str.toLowerCase(Locale.US)) {
            case "1":
            case "true":
                return Boolean.TRUE;
            case "0":
            case "false":
                return Boolean.FALSE;
            default:
                return null;
        }
    }

    private static Integer tryParseInteger(String str) {
        try {
            return Integer.valueOf(str);
        } catch (NumberFormatException e) {
            return null;
        }
    }

    private static Integer tryParseUInt(String str) {
        try {
            return Integer.parseUnsignedInt(str);
        } catch (NumberFormatException e) {
            return null;
        }
    }

    private static Long tryParseLong(String str) {
        try {
            return Long.valueOf(str);
        } catch (NumberFormatException e) {
            return null;
        }
    }

    private static Long tryParseULong(String str) {
        try {
            return Long.parseUnsignedLong(str);
        } catch (NumberFormatException e) {
            return null;
        }
    }

    private static Double tryParseDouble(String str) {
        try {
            return Double.valueOf(str);
        } catch (NumberFormatException e) {
            return null;
        }
    }

    private static String tryParseString(String str) {
        return "".equals(str) ? null : str;
    }

    private static <T extends Enum<T>> T tryParseEnum(Class<T> enumType, String str) {
        try {
            return Enum.valueOf(enumType, str.toUpperCase(Locale.US));
        } catch (IllegalArgumentException e) {
            return null;
        }
    }

    private static <T> List<T> tryParseList(Function<String, T> elementParser, String str) {
        if ("".equals(str)) return new ArrayList<>();

        List<T> ret = new ArrayList<>();

        int p = 0;
        for (;;) {
            StringBuilder sb = new StringBuilder();
            while (p < str.length() && str.charAt(p) != ',') {
                if (str.charAt(p) == '\\') ++p;
                if (p == str.length()) break;
                sb.append(str.charAt(p++));
            }
            ret.add(elementParser.apply(sb.toString()));
            if (p == str.length()) break;
            ++p;
        }

        return ret;
    }

    private static <T extends Enum<T>> List<T> tryParseEnumList(Class<T> enumType, String str) {
        if ("".equals(str)) return new ArrayList<>();

        List<T> ret = new ArrayList<>();

        for (String element : str.split(",")) {
            ret.add(tryParseEnum(enumType, element));
        }

        return ret;
    }

    private static String escape(String str) {
        return str.replaceAll("([\\\\,])", "\\\\$1");
    }

    private static <T> String formatList(List<T> list) {
        StringJoiner joiner = new StringJoiner(",");

        for (T element : list) {
            joiner.add(element == null ? "" : escape(element.toString()));
        }

        return joiner.toString();
    }

    private static String formatUIntList(List<Integer> list) {
        StringJoiner joiner = new StringJoiner(",");

        for (Integer element : list) {
            joiner.add(element == null ? "" : escape(Integer.toUnsignedString(element)));
        }

        return joiner.toString();
    }

    private static String formatULongList(List<Long> list) {
        StringJoiner joiner = new StringJoiner(",");

        for (Long element : list) {
            joiner.add(element == null ? "" : escape(Long.toUnsignedString(element)));
        }

        return joiner.toString();
    }

    private static <T extends Enum<T>> String formatEnumList(List<T> list, Function<T, String> elementFormatter) {
        StringJoiner joiner = new StringJoiner(",");

        for (T element : list) {
            joiner.add(element == null ? "" : elementFormatter.apply(element));
        }

        return joiner.toString();
    }

    public static Optional<Integer> test_int() {
        String value = SystemProperties.get("vendor.test_int");
        return Optional.ofNullable(tryParseInteger(value));
    }

    public static void test_int(Integer value) {
        SystemProperties.set("vendor.test_int", value == null ? "" : value.toString());
    }

    public static Optional<String> test_string() {
        String value = SystemProperties.get("vendor.test.string");
        if ("".equals(value)) {
            Log.v("TestProperties", "prop vendor.test.string doesn't exist; fallback to legacy prop vendor.old.string");
            value = SystemProperties.get("vendor.old.string");
        }
        return Optional.ofNullable(tryParseString(value));
    }

    public static Optional<Boolean> test_BOOLeaN() {
        String value = SystemProperties.get("ro.vendor.test.b");
        return Optional.ofNullable(tryParseBoolean(value));
    }

    public static void test_BOOLeaN(Boolean value) {
        SystemProperties.set("ro.vendor.test.b", value == null ? "" : value.toString());
    }

    public static Optional<Long> vendor_os_test_long() {
        String value = SystemProperties.get("vendor.vendor_os_test-long");
        return Optional.ofNullable(tryParseLong(value));
    }

    public static void vendor_os_test_long(Long value) {
        SystemProperties.set("vendor.vendor_os_test-long", value == null ? "" : value.toString());
    }

    public static List<Integer> test_list_int() {
        String value = SystemProperties.get("vendor.test_list_int");
        return tryParseList(v -> tryParseInteger(v), value);
    }

    public static void test_list_int(List<Integer> value) {
        SystemProperties.set("vendor.test_list_int", value == null ? "" : formatList(value));
    }

    @Deprecated
    public static List<String> test_strlist() {
        String value = SystemProperties.get("vendor.test_strlist");
        return tryParseList(v -> tryParseString(v), value);
    }

    @Deprecated
    public static void test_strlist(List<String> value) {
        SystemProperties.set("vendor.test_strlist", value == null ? "" : formatList(value));
    }
}
)s";

constexpr const char* kExpectedInternalOutput =
    R"s(// Generated by the sysprop generator. DO NOT EDIT!

package com.somecompany;

import android.os.SystemProperties;
import android.util.Log;

import java.lang.StringBuilder;
import java.util.ArrayList;
import java.util.function.Function;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.StringJoiner;
import java.util.stream.Collectors;

public final class TestProperties {
    private TestProperties () {}

    private static Boolean tryParseBoolean(String str) {
        if (str == null) return null;
        switch (str.toLowerCase(Locale.US)) {
            case "1":
            case "true":
                return Boolean.TRUE;
            case "0":
            case "false":
                return Boolean.FALSE;
            default:
                return null;
        }
    }

    private static Integer tryParseInteger(String str) {
        try {
            return Integer.valueOf(str);
        } catch (NumberFormatException e) {
            return null;
        }
    }

    private static Integer tryParseUInt(String str) {
        try {
            return Integer.parseUnsignedInt(str);
        } catch (NumberFormatException e) {
            return null;
        }
    }

    private static Long tryParseLong(String str) {
        try {
            return Long.valueOf(str);
        } catch (NumberFormatException e) {
            return null;
        }
    }

    private static Long tryParseULong(String str) {
        try {
            return Long.parseUnsignedLong(str);
        } catch (NumberFormatException e) {
            return null;
        }
    }

    private static Double tryParseDouble(String str) {
        try {
            return Double.valueOf(str);
        } catch (NumberFormatException e) {
            return null;
        }
    }

    private static String tryParseString(String str) {
        return "".equals(str) ? null : str;
    }

    private static <T extends Enum<T>> T tryParseEnum(Class<T> enumType, String str) {
        try {
            return Enum.valueOf(enumType, str.toUpperCase(Locale.US));
        } catch (IllegalArgumentException e) {
            return null;
        }
    }

    private static <T> List<T> tryParseList(Function<String, T> elementParser, String str) {
        if ("".equals(str)) return new ArrayList<>();

        List<T> ret = new ArrayList<>();

        int p = 0;
        for (;;) {
            StringBuilder sb = new StringBuilder();
            while (p < str.length() && str.charAt(p) != ',') {
                if (str.charAt(p) == '\\') ++p;
                if (p == str.length()) break;
                sb.append(str.charAt(p++));
            }
            ret.add(elementParser.apply(sb.toString()));
            if (p == str.length()) break;
            ++p;
        }

        return ret;
    }

    private static <T extends Enum<T>> List<T> tryParseEnumList(Class<T> enumType, String str) {
        if ("".equals(str)) return new ArrayList<>();

        List<T> ret = new ArrayList<>();

        for (String element : str.split(",")) {
            ret.add(tryParseEnum(enumType, element));
        }

        return ret;
    }

    private static String escape(String str) {
        return str.replaceAll("([\\\\,])", "\\\\$1");
    }

    private static <T> String formatList(List<T> list) {
        StringJoiner joiner = new StringJoiner(",");

        for (T element : list) {
            joiner.add(element == null ? "" : escape(element.toString()));
        }

        return joiner.toString();
    }

    private static String formatUIntList(List<Integer> list) {
        StringJoiner joiner = new StringJoiner(",");

        for (Integer element : list) {
            joiner.add(element == null ? "" : escape(Integer.toUnsignedString(element)));
        }

        return joiner.toString();
    }

    private static String formatULongList(List<Long> list) {
        StringJoiner joiner = new StringJoiner(",");

        for (Long element : list) {
            joiner.add(element == null ? "" : escape(Long.toUnsignedString(element)));
        }

        return joiner.toString();
    }

    private static <T extends Enum<T>> String formatEnumList(List<T> list, Function<T, String> elementFormatter) {
        StringJoiner joiner = new StringJoiner(",");

        for (T element : list) {
            joiner.add(element == null ? "" : elementFormatter.apply(element));
        }

        return joiner.toString();
    }

    public static Optional<Double> test_double() {
        String value = SystemProperties.get("vendor.test_double");
        return Optional.ofNullable(tryParseDouble(value));
    }

    public static void test_double(Double value) {
        SystemProperties.set("vendor.test_double", value == null ? "" : value.toString());
    }

    public static Optional<Integer> test_int() {
        String value = SystemProperties.get("vendor.test_int");
        return Optional.ofNullable(tryParseInteger(value));
    }

    public static void test_int(Integer value) {
        SystemProperties.set("vendor.test_int", value == null ? "" : value.toString());
    }

    public static Optional<String> test_string() {
        String value = SystemProperties.get("vendor.test.string");
        if ("".equals(value)) {
            Log.v("TestProperties", "prop vendor.test.string doesn't exist; fallback to legacy prop vendor.old.string");
            value = SystemProperties.get("vendor.old.string");
        }
        return Optional.ofNullable(tryParseString(value));
    }

    public static enum test_enum_values {
        A("a"),
        B("b"),
        C("c"),
        D("D"),
        E("e"),
        F("f"),
        G("G");
        private final String propValue;
        private test_enum_values(String propValue) {
            this.propValue = propValue;
        }
        public String getPropValue() {
            return propValue;
        }
    }

    public static Optional<test_enum_values> test_enum() {
        String value = SystemProperties.get("vendor.test.enum");
        return Optional.ofNullable(tryParseEnum(test_enum_values.class, value));
    }

    public static void test_enum(test_enum_values value) {
        SystemProperties.set("vendor.test.enum", value == null ? "" : value.getPropValue());
    }

    public static Optional<Boolean> test_BOOLeaN() {
        String value = SystemProperties.get("ro.vendor.test.b");
        return Optional.ofNullable(tryParseBoolean(value));
    }

    public static void test_BOOLeaN(Boolean value) {
        SystemProperties.set("ro.vendor.test.b", value == null ? "" : value.toString());
    }

    public static Optional<Long> vendor_os_test_long() {
        String value = SystemProperties.get("vendor.vendor_os_test-long");
        return Optional.ofNullable(tryParseLong(value));
    }

    public static void vendor_os_test_long(Long value) {
        SystemProperties.set("vendor.vendor_os_test-long", value == null ? "" : value.toString());
    }

    public static List<Double> test_double_list() {
        String value = SystemProperties.get("vendor.test_double_list");
        return tryParseList(v -> tryParseDouble(v), value);
    }

    public static void test_double_list(List<Double> value) {
        SystemProperties.set("vendor.test_double_list", value == null ? "" : formatList(value));
    }

    public static List<Integer> test_list_int() {
        String value = SystemProperties.get("vendor.test_list_int");
        return tryParseList(v -> tryParseInteger(v), value);
    }

    public static void test_list_int(List<Integer> value) {
        SystemProperties.set("vendor.test_list_int", value == null ? "" : formatList(value));
    }

    @Deprecated
    public static List<String> test_strlist() {
        String value = SystemProperties.get("vendor.test_strlist");
        return tryParseList(v -> tryParseString(v), value);
    }

    @Deprecated
    public static void test_strlist(List<String> value) {
        SystemProperties.set("vendor.test_strlist", value == null ? "" : formatList(value));
    }

    public static enum el_values {
        ENU("enu"),
        MVA("mva"),
        LUE("lue");
        private final String propValue;
        private el_values(String propValue) {
            this.propValue = propValue;
        }
        public String getPropValue() {
            return propValue;
        }
    }

    @Deprecated
    public static List<el_values> el() {
        String value = SystemProperties.get("vendor.el");
        return tryParseEnumList(el_values.class, value);
    }

    @Deprecated
    public static void el(List<el_values> value) {
        SystemProperties.set("vendor.el", value == null ? "" : formatEnumList(value, el_values::getPropValue));
    }
}
)s";

}  // namespace

using namespace std::string_literals;

TEST(SyspropTest, JavaGenTest) {
  TemporaryFile temp_file;

  // strlen is optimized for constants, so don't worry about it.
  ASSERT_EQ(write(temp_file.fd, kTestSyspropFile, strlen(kTestSyspropFile)),
            strlen(kTestSyspropFile));
  close(temp_file.fd);
  temp_file.fd = -1;

  TemporaryDir temp_dir;

  std::pair<sysprop::Scope, const char*> tests[] = {
      {sysprop::Scope::Internal, kExpectedInternalOutput},
      {sysprop::Scope::Public, kExpectedPublicOutput},
  };

  for (auto [scope, expected_output] : tests) {
    ASSERT_RESULT_OK(GenerateJavaLibrary(temp_file.path, scope, temp_dir.path));

    std::string java_output_path =
        temp_dir.path + "/com/somecompany/TestProperties.java"s;

    std::string java_output;
    ASSERT_TRUE(
        android::base::ReadFileToString(java_output_path, &java_output, true));
    EXPECT_EQ(java_output, expected_output);

    unlink(java_output_path.c_str());
    rmdir((temp_dir.path + "/com/somecompany"s).c_str());
    rmdir((temp_dir.path + "/com"s).c_str());
  }
}
