/*
 * Copyright (c) 2017-2022 XMLmind Software. All rights reserved.
 *
 * Author: Hussein Shafie
 *
 * This file is part of the XMLmind Assembly Processor project.
 * For conditions of distribution and use, see the accompanying legal.txt file.
 */
package com.xmlmind.domutil;

import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Properties;
import org.w3c.dom.Element;
import com.xmlmind.util.LocaleUtil;
import com.xmlmind.util.URIComponent;
import com.xmlmind.util.URLUtil;
import com.xmlmind.util.XMLResolver;

public final class LocalizedText {
    private static final HashMap<String,Properties> resToProps = 
        new HashMap<String,Properties>();

    public static String get(String key, Element element, String fallback,
                             String resource, XMLResolver resolver,
                             Class<?> cls) {
        String localized = null;

        String lang = DOMUtil.lookupXMLLang(element);
        if (lang == null) {
            lang = "en";
        }
        String[] langParts = new String[2];
        lang = LocaleUtil.normalizeLang(lang, langParts);

        String location;
        Properties props;

        if (langParts[1] != null) {
            // Use for example messages_fr-BE.xml if any.

            location = addLang(resource, langParts);
            props = getProperties(location, resolver, cls);
            localized = props.getProperty(key);

            /*
            System.err.println("LocalizedText.get>>> " + 
                               location + "->" +  key + "=" + localized);
            */
        }

        if (localized == null) {
            // Use for example messages_fr.xml if any.

            langParts[1] = null;
            location = addLang(resource, langParts);
            props = getProperties(location, resolver, cls);
            localized = props.getProperty(key);

            /*
            System.err.println("LocalizedText.get>>> " + 
                               location + "->" +  key + "=" + localized);
            */
        }

        if (localized == null) {
            // Use for example messages.xml if any.

            props = getProperties(resource, resolver, cls);
            localized = props.getProperty(key);

            /*
            System.err.println("LocalizedText.get>>> " + 
                               resource + "->" +  key + "=" + localized);
            */
        }

        if (localized == null) {
            localized = fallback;
        }
        return localized;
    }

    private static String addLang(String resource, String[] langParts) {
        int dot = resource.lastIndexOf('.');
        if (dot > 0 && dot < resource.length()-1) {
            StringBuilder buffer = new StringBuilder();
            buffer.append(resource.substring(0, dot));
            buffer.append('_');
            buffer.append(langParts[0]);
            if (langParts[1] != null) {
                buffer.append('-');
                buffer.append(langParts[1]);
            }
            buffer.append(resource.substring(dot));

            resource = buffer.toString();
        }

        return resource;
    }

    private static Properties getProperties(String resource,
                                            XMLResolver resolver,
                                            Class<?> cls) {
        Properties props = null;

        synchronized (resToProps) {
            props = resToProps.get(resource);
            if (props == null) {
                props = new Properties();
                try {
                    boolean loaded =
                        loadProperties(props, resource, resolver, cls);

                    /*
                    if (loaded) {
                        System.err.println("LocalizedText.getProperties>>>" +
                                           " loaded " + resource + 
                                           ":\n---\n" + props + "\n---");
                    }
                    */
                } catch (IOException ignored) {
                    ignored.printStackTrace();
                }

                resToProps.put(resource, props);
            }
        }

        return props;
    }

    private static boolean loadProperties(Properties props, String resource,
                                          XMLResolver resolver, Class<?> cls) 
        throws IOException {
        boolean loaded = false;
        InputStream src = null;

        if (resolver != null) {
            String location = resolver.resolveURI(resource);
            if (location != null) {
                try {
                    URL url = URLUtil.createURL(location);
                    src = URLUtil.openStreamNoCache(url);
                } catch (Exception ignored) {}
            }
        }

        if (src == null && cls != null) {
            String name = URIComponent.getRawBaseName(resource);
            if (name != null) {
                URL url = cls.getResource(name);
                if (url != null) {
                    try {
                        src = URLUtil.openStreamNoCache(url);
                    } catch (IOException ignored) {}
                }
            }
        }

        if (src != null) {
            BufferedInputStream in = new BufferedInputStream(src, 65536);
            try {
                props.loadFromXML(in);
                loaded = true;
            } finally {
                in.close();
            }
        }

        return loaded;
    }
}
