/* ====================================================================
   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.
==================================================================== */

package org.apache.poi.hssf.record;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.HexRead;
import org.junit.jupiter.api.Test;

/**
 * Tests the record factory
 */
final class TestRecordFactory {


	/**
	 * TEST NAME:  Test Basic Record Construction <P>
	 * OBJECTIVE:  Test that the RecordFactory given the required parameters for know
	 *             record types can construct the proper record w/values.<P>
	 * SUCCESS:	Record factory creates the records with the expected values.<P>
	 * FAILURE:	The wrong records are creates or contain the wrong values <P>
	 *
	 */
    @Test
	void testBasicRecordConstruction() {
		short recType = BOFRecord.sid;
		byte[]   data	= {
			0, 6, 5, 0, -2, 28, -51, 7, -55, 64, 0, 0, 6, 1, 0, 0
		};
		Record[] record  = RecordFactory.createRecord(TestcaseRecordInputStream.create(recType, data));

		assertEquals(BOFRecord.class.getName(),
					 record[ 0 ].getClass().getName());
		BOFRecord bofRecord = ( BOFRecord ) record[ 0 ];

		assertEquals(7422, bofRecord.getBuild());
		assertEquals(1997, bofRecord.getBuildYear());
		assertEquals(16585, bofRecord.getHistoryBitMask());
		assertEquals(20, bofRecord.getRecordSize());
		assertEquals(262, bofRecord.getRequiredVersion());
		assertEquals(2057, bofRecord.getSid());
		assertEquals(5, bofRecord.getType());
		assertEquals(1536, bofRecord.getVersion());
		recType = MMSRecord.sid;
		data = new byte[] {
			0, 0
		};
		record  = RecordFactory.createRecord(TestcaseRecordInputStream.create(recType, data));
		assertEquals(MMSRecord.class.getName(),
					 record[ 0 ].getClass().getName());
		MMSRecord mmsRecord = ( MMSRecord ) record[ 0 ];

		assertEquals(0, mmsRecord.getAddMenuCount());
		assertEquals(0, mmsRecord.getDelMenuCount());
		assertEquals(6, mmsRecord.getRecordSize());
		assertEquals(193, mmsRecord.getSid());
	}

	/**
	 * TEST NAME:  Test Special Record Construction <P>
	 * OBJECTIVE:  Test that the RecordFactory given the required parameters for
	 *			 constructing a RKRecord will return a NumberRecord.<P>
	 * SUCCESS:	Record factory creates the Number record with the expected values.<P>
	 * FAILURE:	The wrong records are created or contain the wrong values <P>
	 *
	 */
    @Test
    void testSpecial() {
		short recType = RKRecord.sid;
		byte[] data = {
			0, 0, 0, 0, 21, 0, 0, 0, 0, 0
		};
		Record[] record  = RecordFactory.createRecord(TestcaseRecordInputStream.create(recType, data));

		assertEquals(NumberRecord.class.getName(),
					 record[ 0 ].getClass().getName());
		NumberRecord numberRecord = ( NumberRecord ) record[ 0 ];

		assertEquals(0, numberRecord.getColumn());
		assertEquals(18, numberRecord.getRecordSize());
		assertEquals(0, numberRecord.getRow());
		assertEquals(515, numberRecord.getSid());
		assertEquals(0.0, numberRecord.getValue(), 0.001);
		assertEquals(21, numberRecord.getXFIndex());
	}

	/**
	 * TEST NAME:  Test Creating ContinueRecords After Unknown Records From An InputStream <P>
	 * OBJECTIVE:  Test that the RecordFactory given an InputStream
	 *             constructs the expected array of records.<P>
	 * SUCCESS:	Record factory creates the expected records.<P>
	 * FAILURE:	The wrong records are created or contain the wrong values <P>
	 */
    @Test
	void testContinuedUnknownRecord() {
		byte[] data = {
			0, -1, 0, 0, // an unknown record with 0 length
			0x3C , 0, 3, 0, 1, 2, 3, // a continuation record with 3 bytes of data
			0x3C , 0, 1, 0, 4 // one more continuation record with 1 byte of data
		};

		ByteArrayInputStream bois = new ByteArrayInputStream(data);
		Record[] records = RecordFactory.createRecords(bois).toArray(new Record[0]);
		assertEquals(3, records.length, "Created record count");
		assertEquals(UnknownRecord.class.getName(), records[ 0 ].getClass().getName(), "1st record's type");
		assertEquals((short)-256, records[0].getSid(), "1st record's sid");
		assertEquals(ContinueRecord.class.getName(), records[ 1 ].getClass().getName(), "2nd record's type");
		ContinueRecord record = (ContinueRecord) records[1];
		assertEquals(0x3C, record.getSid(), "2nd record's sid");
		assertEquals(1, record.getData()[ 0 ], "1st data byte");
		assertEquals(2, record.getData()[ 1 ], "2nd data byte");
		assertEquals(3, record.getData()[ 2 ], "3rd data byte");
		assertEquals(ContinueRecord.class.getName(), records[ 2 ].getClass().getName(), "3rd record's type");
		record = (ContinueRecord) records[2];
		assertEquals(0x3C, record.getSid(), "3nd record's sid");
		assertEquals(4, record.getData()[ 0 ], "4th data byte");
	}

	/**
	 * Drawing records have a very strange continue behaviour.
	 * There can actually be OBJ records mixed between the continues.
	 * Record factory must preserve this structure when reading records.
	 */
    @Test
	void testMixedContinue() throws IOException {
		// Adapted from a real test sample file 39512.xls (Offset 0x4854).
		// See Bug 39512 for details.
		String dump =
				//OBJ
				"5D 00 48 00 15 00 12 00 0C 00 3C 00 11 00 A0 2E 03 01 CC 42 " +
				"CF 00 00 00 00 00 0A 00 0C 00 00 00 00 00 00 00 00 00 00 00 " +
				"03 00 0B 00 06 00 28 01 03 01 00 00 12 00 08 00 00 00 00 00 " +
				"00 00 03 00 11 00 04 00 3D 00 00 00 00 00 00 00 " +
				 //MSODRAWING
				"EC 00 08 00 00 00 0D F0 00 00 00 00 " +
				//TXO (and 2 trailing CONTINUE records)
				"B6 01 12 00 22 02 00 00 00 00 00 00 00 00 10 00 10 00 00 00 00 00 " +
				"3C 00 11 00 00 4F 70 74 69 6F 6E 20 42 75 74 74 6F 6E 20 33 39 " +
				"3C 00 10 00 00 00 05 00 00 00 00 00 10 00 00 00 00 00 00 00 " +
				// another CONTINUE
				"3C 00 7E 00 0F 00 04 F0 7E 00 00 00 92 0C 0A F0 08 00 00 00 " +
				"3D 04 00 00 00 0A 00 00 A3 00 0B F0 3C 00 00 00 7F 00 00 01 " +
				"00 01 80 00 8C 01 03 01 85 00 01 00 00 00 8B 00 02 00 00 00 " +
				"BF 00 08 00 1A 00 7F 01 29 00 29 00 81 01 41 00 00 08 BF 01 " +
				"00 00 10 00 C0 01 40 00 00 08 FF 01 00 00 08 00 00 00 10 F0 " +
				"12 00 00 00 02 00 02 00 A0 03 18 00 B5 00 04 00 30 02 1A 00 " +
				"00 00 00 00 11 F0 00 00 00 00 " +
				//OBJ
				"5D 00 48 00 15 00 12 00 0C 00 3D 00 11 00 8C 01 03 01 C8 59 CF 00 00 " +
				"00 00 00 0A 00 0C 00 00 00 00 00 00 00 00 00 00 00 03 00 0B 00 06 00 " +
				"7C 16 03 01 00 00 12 00 08 00 00 00 00 00 00 00 03 00 11 00 04 00 01 " +
				"00 00 00 00 00 00 00";
		byte[] data = HexRead.readFromString(dump);

		List<org.apache.poi.hssf.record.Record> records = RecordFactory.createRecords(new ByteArrayInputStream(data));
		assertEquals(5, records.size());
		assertTrue(records.get(0) instanceof ObjRecord);
		assertTrue(records.get(1) instanceof DrawingRecord);
		assertTrue(records.get(2) instanceof TextObjectRecord);
		assertTrue(records.get(3) instanceof ContinueRecord);
		assertTrue(records.get(4) instanceof ObjRecord);

		//serialize and verify that the serialized data is the same as the original
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		for(org.apache.poi.hssf.record.Record rec : records){
			out.write(rec.serialize());
		}

		byte[] ser = out.toByteArray();
		assertEquals(data.length, ser.length);
		assertArrayEquals(data, ser);
	}

    @Test
	void testNonZeroPadding_bug46987() throws IOException {
		Record[] recs = {
			new BOFRecord(),
			new WriteAccessRecord(), // need *something* between BOF and EOF
			EOFRecord.instance,
			BOFRecord.createSheetBOF(),
			EOFRecord.instance,
		};
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		for (org.apache.poi.hssf.record.Record rec : recs) {
			try {
				baos.write(rec.serialize());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		//simulate the bad padding at the end of the workbook stream in attachment 23483 of bug 46987
		baos.write(0x00);
		baos.write(0x11);
		baos.write(0x00);
		baos.write(0x02);
		for (int i = 0; i < 192; i++) {
			baos.write(0x00);
		}


		POIFSFileSystem fs = new POIFSFileSystem();
        fs.createDocument(new ByteArrayInputStream(baos.toByteArray()), "dummy");
		InputStream is = fs.getRoot().createDocumentInputStream("dummy");

		List<org.apache.poi.hssf.record.Record> outRecs = RecordFactory.createRecords(is);
		// Buffer underrun - requested 512 bytes but 192 was available
		assertEquals(5, outRecs.size());
		fs.close();
	}
}
