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

import com.android.tools.layoutlib.annotations.Nullable;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.io.File;
import java.io.FileWriter;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;


public class ResourceConverter {

    /**
     * Convert the Android strings.xml into generic Java strings.properties.
     */
    public static void main(String[] args) throws Exception {
        System.out.println("Parsing input...");
        Map<String, String> map = loadStrings("./validator/resources/strings.xml");
        System.out.println("Writing to output...");
        writeStrings(map, "./validator/resources/strings.properties");
        System.out.println("Finished converting.");
    }

    /**
     * Writes <name, value> pair to outputPath.
     */
    private static void writeStrings(Map<String, String> map, String outputPath) throws Exception {
        File output = new File(outputPath);
        output.createNewFile();
        try (FileWriter writer = new FileWriter(output, StandardCharsets.UTF_8)) {
            writer.write(getCopyRight());
            writer.write("\n");
            for (Entry<String, String> entry : map.entrySet()) {
                String name = entry.getKey();
                String value = entry.getValue();
                writer.write(name + " = " + value + "\n");
            }
        }
    }

    /**
     * Very hacky parser for Android-understood-values.xml. It parses <string> </string>
     * tags, and retrieve the name and the value associated.
     *
     * @param path to .xml containing android strings
     * @return Map containing name and values.
     */
    @Nullable
    private static Map<String, String> loadStrings(String path)
            throws Exception {
        // Use ordered map to minimize changes to strings.properties in git.
        Map<String, String> toReturn = new LinkedHashMap<>();

        File file = new File(path);
        if (!file.exists()) {
            System.err.println("The input file "+ path + " does not exist. Terminating.");
            return toReturn;
        }

        DocumentBuilder documentBuilder = DocumentBuilderFactory
                .newInstance().newDocumentBuilder();
        Document document = documentBuilder.parse(file);
        NodeList nodeList = document.getElementsByTagName("string");
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            String name = node.getAttributes().getNamedItem("name").getNodeValue();

            StringBuilder valueBuilder = new StringBuilder();
            try {
                /*
                  This is a very hacky way to bypass "ns1:g" tag in android's .xml.
                  Ideally we'll read the tag from the parent and apply it here, but it being the
                  deep node list I'm not currently sure how to parse it safely. Might need to look
                  into IntelliJ PSI tree we have in Studio. But I didn't want to add unnecessary
                  deps to LayoutLib.

                  It also means resource namespaces are rendered useless after conversion.
                 */
                for (int j = 0; j < node.getChildNodes().getLength(); j++) {
                    Node child = node.getChildNodes().item(j);
                    String toAdd;
                    if ("ns1:g".equals(child.getNodeName())) {
                        toAdd = child.getFirstChild().getNodeValue();
                    } else if ("xliff:g".equals(child.getNodeName())) {
                        toAdd = child.getFirstChild().getNodeValue();
                    } else {
                        toAdd = child.getNodeValue();
                    }
                    // Replace all tab, newline and multi indentations.
                    toAdd = toAdd.replaceAll("[\n\t]", "");
                    toAdd = toAdd.replaceAll("[ ]+", " ");
                    valueBuilder.append(toAdd);
                }
                String finalString = valueBuilder.toString().trim();
                toReturn.put(name, finalString);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return toReturn;
    }

    private static String getCopyRight() {
        return """

                #
                # Copyright (C) 2020 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.
                #""";
    }
}
