/*
 * 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.
 */
#include <log4cxx/logstring.h>
#include <log4cxx/helpers/resourcebundle.h>
#include <log4cxx/helpers/propertyresourcebundle.h>
#include <log4cxx/helpers/loader.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/helpers/locale.h>

using namespace LOG4CXX_NS;
using namespace LOG4CXX_NS::helpers;

IMPLEMENT_LOG4CXX_OBJECT(ResourceBundle)

ResourceBundlePtr ResourceBundle::getBundle(const LogString& baseName,
	const Locale& locale)
{
	std::vector<LogString> bundlesNames;

	if (!locale.getVariant().empty())
	{
		bundlesNames.push_back(baseName + LOG4CXX_STR("_") +
			locale.getLanguage() + LOG4CXX_STR("_") +
			locale.getCountry() + LOG4CXX_STR("_") +
			locale.getVariant());
	}

	if (!locale.getCountry().empty())
	{
		bundlesNames.push_back(baseName + LOG4CXX_STR("_") +
			locale.getLanguage() + LOG4CXX_STR("_") +
			locale.getCountry());
	}

	if (!locale.getLanguage().empty())
	{
		bundlesNames.push_back(baseName + LOG4CXX_STR("_") +
			locale.getLanguage());
	}

	bundlesNames.push_back(baseName);

	PropertyResourceBundlePtr resourceBundle, previous;
	for (auto bundleName : bundlesNames)
	{
		PropertyResourceBundlePtr current;

		// Try loading a class which implements ResourceBundle
		try
		{
			const Class& classObj = Loader::loadClass(bundleName);
			ObjectPtr obj = ObjectPtr(classObj.newInstance());
			current = LOG4CXX_NS::cast<PropertyResourceBundle>(obj);
		}
		catch (ClassNotFoundException&)
		{
			current.reset();
		}

		// No class found, then try to create a PropertyResourceBundle from a file
		if (!current)
		{
			InputStreamPtr bundleStream =
				Loader::getResourceAsStream(
					bundleName + LOG4CXX_STR(".properties"));

			if (!bundleStream)
			{
				continue;
			}

			try
			{
				current = std::make_shared<PropertyResourceBundle>(bundleStream);
			}
			catch (Exception&)
			{
				throw;
			}
		}

		// Add the new resource bundle to the hierarchy
		if (!resourceBundle)
		{
			resourceBundle = current;
			previous = current;
		}
		else
		{
			previous->setParent(current);
			previous = current;
		}
	}

	// no resource bundle found at all, then throw exception
	if (!resourceBundle)
	{
		throw MissingResourceException(
			((LogString) LOG4CXX_STR("Missing resource bundle ")) + baseName);
	}

	return resourceBundle;
}

