/*
 * 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/file.h>
#include "logunit.h"
#include "insertwide.h"
#include <log4cxx/helpers/pool.h>
#include <apr_errno.h>
#include <log4cxx/helpers/exception.h>
#include <log4cxx/helpers/fileinputstream.h>

#include <log4cxx/helpers/outputstreamwriter.h>
#include <log4cxx/helpers/fileoutputstream.h>
#include <log4cxx/helpers/inputstreamreader.h>
#include <log4cxx/helpers/fileinputstream.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/bytebuffer.h>
#include <log4cxx/helpers/transcoder.h>

#if LOG4CXX_CFSTRING_API
	#include <CoreFoundation/CFString.h>
#endif

using namespace log4cxx;
using namespace log4cxx::helpers;


LOGUNIT_CLASS(FileTestCase)
{
	LOGUNIT_TEST_SUITE(FileTestCase);
	LOGUNIT_TEST(defaultConstructor);
	LOGUNIT_TEST(defaultExists);
	LOGUNIT_TEST(defaultRead);
	LOGUNIT_TEST(propertyRead);
	LOGUNIT_TEST(propertyExists);
	LOGUNIT_TEST(fileWrite1);
#if LOG4CXX_WCHAR_T_API
	LOGUNIT_TEST(wcharConstructor);
#endif
#if LOG4CXX_CFSTRING_API
	LOGUNIT_TEST(cfstringConstructor);
#endif
	LOGUNIT_TEST(copyConstructor);
	LOGUNIT_TEST(assignment);
	LOGUNIT_TEST(deleteBackslashedFileName);
	LOGUNIT_TEST(testSplitMultibyteUtf8);
	LOGUNIT_TEST(testInvalidUtf8);
	LOGUNIT_TEST_SUITE_END();

#ifdef _DEBUG
	struct Fixture
	{
		Fixture() {
			helpers::LogLog::setInternalDebugging(true);
		}
	} suiteFixture;
#endif

public:
	void defaultConstructor()
	{
		File defFile;
		LOGUNIT_ASSERT_EQUAL((LogString) LOG4CXX_STR(""), defFile.getPath());
	}



	void defaultExists()
	{
		File defFile;
		bool exists = defFile.exists();
		LOGUNIT_ASSERT_EQUAL(false, exists);
	}

	// check default constructor. read() throws an exception
	// if no file name was given.
	void defaultRead()
	{
		File defFile;

		try
		{
			InputStreamPtr defInput = FileInputStreamPtr(new FileInputStream(defFile));
			InputStreamReaderPtr inputReader = InputStreamReaderPtr(new InputStreamReader(defInput));
			LogString contents(inputReader->read());
			LOGUNIT_ASSERT(false);
		}
		catch (IOException& ex)
		{
			LOG4CXX_DECODE_CHAR(msg, ex.what());
			LogLog::debug(msg);
		}
	}


#if LOG4CXX_WCHAR_T_API
	void wcharConstructor()
	{
		File propFile(L"input/patternLayout1.properties");
		bool exists = propFile.exists();
		LOGUNIT_ASSERT_EQUAL(true, exists);
	}
#endif

#if LOG4CXX_CFSTRING_API
	void cfstringConstructor()
	{
		File propFile(CFSTR("input/patternLayout1.properties"));
		bool exists = propFile.exists();
		LOGUNIT_ASSERT_EQUAL(true, exists);
	}
#endif

	void copyConstructor()
	{
		File propFile("input/patternLayout1.properties");
		File copy(propFile);
		bool exists = copy.exists();
		LOGUNIT_ASSERT_EQUAL(true, exists);
	}

	void assignment()
	{
		File propFile("input/patternLayout1.properties");
		File copy = propFile;
		bool exists = copy.exists();
		LOGUNIT_ASSERT_EQUAL(true, exists);
	}

	void propertyRead()
	{
		File propFile("input/patternLayout1.properties");
		InputStreamPtr propStream = FileInputStreamPtr(new FileInputStream(propFile));
		InputStreamReaderPtr propReader = InputStreamReaderPtr(new InputStreamReader(propStream));
		LogString props(propReader->read());
		LogString line1(LOG4CXX_STR("# Licensed to the Apache Software Foundation (ASF) under one or more"));
		LOGUNIT_ASSERT_EQUAL(line1, props.substr(0, line1.length()));
	}

	void propertyExists()
	{
		File propFile("input/patternLayout1.properties");
		bool exists = propFile.exists();
		LOGUNIT_ASSERT_EQUAL(true, exists);
	}

	void fileWrite1()
	{
		OutputStreamPtr fos = FileOutputStreamPtr(
				new FileOutputStream(LOG4CXX_STR("output/fileWrite1.txt")));
		OutputStreamWriterPtr osw = OutputStreamWriterPtr(new OutputStreamWriter(fos));

		LogString greeting(LOG4CXX_STR("Hello, World"));
		greeting.append(LOG4CXX_EOL);
		osw->write(greeting);

		InputStreamPtr is = FileInputStreamPtr(
				new FileInputStream(LOG4CXX_STR("output/fileWrite1.txt")));
		InputStreamReaderPtr isr = InputStreamReaderPtr(new InputStreamReader(is));
		LogString reply = isr->read();

		LOGUNIT_ASSERT_EQUAL(greeting, reply);
	}

	/**
	 *  Tests conversion of backslash containing file names.
	 *  Would cause infinite loop due to bug LOGCXX-105.
	 */
	void deleteBackslashedFileName()
	{
		File file("output\\bogus.txt");
		file.deleteFile();
	}

	class MockInputStream : public InputStream
	{
		ByteBuffer m_data;
	public:
		MockInputStream(const char* data, size_t charCount)
			: m_data(const_cast<char*>(data), charCount)
		{}

		int read(ByteBuffer& dst) override
		{
			auto availableBytes = m_data.remaining();
			if (availableBytes < 1)
				return -1;
			int count = 0;
			for (auto p = m_data.current(); count < availableBytes && dst.put(*p); ++p)
				++count;
			m_data.increment_position(count);
			return count;
		}

		void close() override {}
	};

	/**
	 * Tests behavior when a multibyte UTF-8 sequence occurs on a read boundary
	 */
	void testSplitMultibyteUtf8()
	{
		// InputStreamReader uses a buffer of size 4096
		std::string input( 4094, 'A' );
		// räksmörgås.josefsson.org
		input.append("\162\303\244\153\163\155\303\266\162\147\303\245\163\056\152\157\163\145\146\163\163\157\156\056\157\162\147");
		InputStreamReader reader(std::make_shared<MockInputStream>(input.c_str(), input.size()), CharsetDecoder::getUTF8Decoder());
		auto contentLS = reader.read();
		LOG4CXX_ENCODE_CHAR(content, contentLS);
		LOGUNIT_ASSERT_EQUAL(input, content);
	}

	/**
	 * Tests behavior given an incomplete multibyte UTF-8 sequence in the input
	 */
	void testInvalidUtf8()
	{
		// 0xC2 is a generic start byte for a 2-byte sequence in UTF-8.
		char input[] = { 'A', (char)0xC2, 'B', 'C', 0 };
		InputStreamReader reader(std::make_shared<MockInputStream>(input, 4), CharsetDecoder::getUTF8Decoder());
		try
		{
			reader.read();
			LOGUNIT_ASSERT(false);
		}
		catch (const Exception& ex)
		{
			LOG4CXX_DECODE_CHAR(msg, ex.what());
			LogLog::debug(msg);
		}
	}
};

LOGUNIT_TEST_SUITE_REGISTRATION(FileTestCase);
