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

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

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.zip.CRC32;

import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.RecordStream;
import org.apache.poi.hssf.model.RowBlocksReader;
import org.apache.poi.hssf.record.BlankRecord;
import org.apache.poi.hssf.record.CellValueRecordInterface;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.MulBlankRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.SharedFormulaRecord;
import org.apache.poi.hssf.record.WindowTwoRecord;
import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.util.HexRead;
import org.junit.jupiter.api.Test;

/**
 * Tests for {@link ValueRecordsAggregate}
 */
final class TestValueRecordsAggregate {
	private static final String ABNORMAL_SHARED_FORMULA_FLAG_TEST_FILE = "AbnormalSharedFormulaFlag.xls";
	private final ValueRecordsAggregate valueRecord = new ValueRecordsAggregate();

	private List<CellValueRecordInterface> getValueRecords() {
	    List<CellValueRecordInterface> list = new ArrayList<>();
	    for ( CellValueRecordInterface rec : valueRecord ) {
	        list.add(rec);
	    }
	    return Collections.unmodifiableList(list);
	}

	/**
	 * Make sure the shared formula DOESNT makes it to the FormulaRecordAggregate when being parsed
	 * as part of the value records
	 */
    @Test
	void testSharedFormula() {
		List<org.apache.poi.hssf.record.Record> records = new ArrayList<>();
		records.add(new FormulaRecord());
		records.add(new SharedFormulaRecord());
		records.add(new WindowTwoRecord());

		constructValueRecord(records);
		List<CellValueRecordInterface> cvrs = getValueRecords();
		//Ensure that the SharedFormulaRecord has been converted
		assertEquals(1, cvrs.size());

		CellValueRecordInterface record = cvrs.get(0);
		assertNotNull( record, "Row contains a value" );
		assertTrue( ( record instanceof FormulaRecordAggregate ), "First record is a FormulaRecordsAggregate");
	}

	private void constructValueRecord(List<org.apache.poi.hssf.record.Record> records) {
		RowBlocksReader rbr = new RowBlocksReader(new RecordStream(records, 0));
		SharedValueManager sfrh = rbr.getSharedFormulaManager();
		RecordStream rs = rbr.getPlainRecordStream();
		while(rs.hasNext()) {
			Record rec = rs.getNext();
			valueRecord.construct((CellValueRecordInterface)rec, rs, sfrh);
		}
	}

	private static List<org.apache.poi.hssf.record.Record> testData() {
		List<org.apache.poi.hssf.record.Record> records = new ArrayList<>();
		FormulaRecord formulaRecord = new FormulaRecord();
		BlankRecord blankRecord = new BlankRecord();
		formulaRecord.setRow(1);
		formulaRecord.setColumn((short) 1);
		blankRecord.setRow(2);
		blankRecord.setColumn((short) 2);
		records.add(formulaRecord);
		records.add(blankRecord);
		records.add(new WindowTwoRecord());
		return records;
	}

    @Test
	void testInsertCell() {
		assertEquals(0, getValueRecords().size());

		BlankRecord blankRecord = newBlankRecord();
		valueRecord.insertCell( blankRecord );
		assertEquals(1, getValueRecords().size());
	}

    @Test
    void testRemoveCell() {
		BlankRecord blankRecord1 = newBlankRecord();
		valueRecord.insertCell( blankRecord1 );
		BlankRecord blankRecord2 = newBlankRecord();
		valueRecord.removeCell( blankRecord2 );
		assertEquals(0, getValueRecords().size());

		// removing an already empty cell just falls through
		valueRecord.removeCell( blankRecord2 );
	}

    @Test
	void testGetPhysicalNumberOfCells() {
		assertEquals(0, valueRecord.getPhysicalNumberOfCells());
		BlankRecord blankRecord1 = newBlankRecord();
		valueRecord.insertCell( blankRecord1 );
		assertEquals(1, valueRecord.getPhysicalNumberOfCells());
		valueRecord.removeCell( blankRecord1 );
		assertEquals(0, valueRecord.getPhysicalNumberOfCells());
	}

    @Test
	void testGetFirstCellNum() {
		assertEquals( -1, valueRecord.getFirstCellNum() );
		valueRecord.insertCell( newBlankRecord( 2, 2 ) );
		assertEquals( 2, valueRecord.getFirstCellNum() );
		valueRecord.insertCell( newBlankRecord( 3, 3 ) );
		assertEquals( 2, valueRecord.getFirstCellNum() );

		// Note: Removal doesn't currently reset the first column.  It probably should but it doesn't.
		valueRecord.removeCell( newBlankRecord( 2, 2 ) );
		assertEquals( 2, valueRecord.getFirstCellNum() );
	}

    @Test
	void testGetLastCellNum() {
		assertEquals( -1, valueRecord.getLastCellNum() );
		valueRecord.insertCell( newBlankRecord( 2, 2 ) );
		assertEquals( 2, valueRecord.getLastCellNum() );
		valueRecord.insertCell( newBlankRecord( 3, 3 ) );
		assertEquals( 3, valueRecord.getLastCellNum() );

		// Note: Removal doesn't currently reset the last column.  It probably should but it doesn't.
		valueRecord.removeCell( newBlankRecord( 3, 3 ) );
		assertEquals( 3, valueRecord.getLastCellNum() );

	}


	private static final class SerializerVisitor implements RecordVisitor {
		private final byte[] _buf;
		private int _writeIndex;
		public SerializerVisitor(byte[] buf) {
			_buf = buf;
			_writeIndex = 0;

		}
		@Override
        public void visitRecord(org.apache.poi.hssf.record.Record r) {
			r.serialize(_writeIndex, _buf);
			_writeIndex += r.getRecordSize();
		}
		public int getWriteIndex() {
			return _writeIndex;
		}
	}

    @Test
	void testSerialize() {
		byte[] expectedArray = HexRead.readFromString(""
				+ "06 00 16 00 " // Formula
				+ "01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "
				+ "01 02 06 00 " // Blank
				+ "02 00 02 00 00 00");
		byte[] actualArray = new byte[expectedArray.length];
		List<org.apache.poi.hssf.record.Record> records = testData();
		constructValueRecord(records);

		SerializerVisitor sv = new SerializerVisitor(actualArray);
		valueRecord.visitCellsForRow(1, sv);
		valueRecord.visitCellsForRow(2, sv);
		assertEquals(actualArray.length, sv.getWriteIndex());
		assertArrayEquals(expectedArray, actualArray);
	}

	private static BlankRecord newBlankRecord() {
		return newBlankRecord( 2, 2 );
	}

	private static BlankRecord newBlankRecord(int col, int row) {
		BlankRecord blankRecord = new BlankRecord();
		blankRecord.setRow( row );
		blankRecord.setColumn( (short) col );
		return blankRecord;
	}

	/**
	 * Sometimes the 'shared formula' flag (<tt>FormulaRecord.isSharedFormula()</tt>) is set when
	 * there is no corresponding SharedFormulaRecord available. SharedFormulaRecord definitions do
	 * not span multiple sheets.  They are are only defined within a sheet, and thus they do not
	 * have a sheet index field (only row and column range fields).<br>
	 * So it is important that the code which locates the SharedFormulaRecord for each
	 * FormulaRecord does not allow matches across sheets.</br>
	 *
	 * Prior to bugzilla 44449 (Feb 2008), POI <tt>ValueRecordsAggregate.construct(int, List)</tt>
	 * allowed <tt>SharedFormulaRecord</tt>s to be erroneously used across sheets.  That incorrect
	 * behaviour is shown by this test.<p>
	 *
	 * <b>Notes on how to produce the test spreadsheet</b>:</p>
	 * The setup for this test (AbnormalSharedFormulaFlag.xls) is rather fragile, insomuchas
	 * re-saving the file (either with Excel or POI) clears the flag.<br>
	 * <ol>
	 * <li>A new spreadsheet was created in Excel (File | New | Blank Workbook).</li>
	 * <li>Sheet3 was deleted.</li>
	 * <li>Sheet2!A1 formula was set to '="second formula"', and fill-dragged through A1:A8.</li>
	 * <li>Sheet1!A1 formula was set to '="first formula"', and also fill-dragged through A1:A8.</li>
	 * <li>Four rows on Sheet1 "5" through "8" were deleted ('delete rows' alt-E D, not 'clear' Del).</li>
	 * <li>The spreadsheet was saved as AbnormalSharedFormulaFlag.xls.</li>
	 * </ol>
	 * Prior to the row delete action the spreadsheet has two <tt>SharedFormulaRecord</tt>s. One
	 * for each sheet. To expose the bug, the shared formulas have been made to overlap.<br>
	 * The row delete action (as described here) seems to to delete the
	 * <tt>SharedFormulaRecord</tt> from Sheet1 (but not clear the 'shared formula' flags.<br>
	 * There are other variations on this theme to create the same effect.
	 *
	 */
    @Test
	void testSpuriousSharedFormulaFlag() throws Exception {

		long actualCRC = getFileCRC(HSSFTestDataSamples.openSampleFileStream(ABNORMAL_SHARED_FORMULA_FLAG_TEST_FILE));
		long expectedCRC = 2277445406L;
		if(actualCRC != expectedCRC) {
			System.err.println("Expected crc " + expectedCRC  + " but got " + actualCRC);
			throw failUnexpectedTestFileChange();
		}
		HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook(ABNORMAL_SHARED_FORMULA_FLAG_TEST_FILE);

		HSSFSheet s = wb.getSheetAt(0); // Sheet1

		String cellFormula;
		cellFormula = getFormulaFromFirstCell(s, 0); // row "1"
		// the problem is not observable in the first row of the shared formula
		assertEquals("\"first formula\"", cellFormula, "Something else wrong with this test case");

		// but the problem is observable in rows 2,3,4
		cellFormula = getFormulaFromFirstCell(s, 1); // row "2"
		assertNotEquals("\"second formula\"", cellFormula, "found bug 44449 (Wrong SharedFormulaRecord was used).");

		assertEquals("\"first formula\"", cellFormula, "Something else wrong with this test case");

		wb.close();
	}
	private static String getFormulaFromFirstCell(HSSFSheet s, int rowIx) {
		return s.getRow(rowIx).getCell(0).getCellFormula();
	}

	/**
	 * If someone opened this particular test file in Excel and saved it, the peculiar condition
	 * which causes the target bug would probably disappear.  This test would then just succeed
	 * regardless of whether the fix was present.  So a CRC check is performed to make it less easy
	 * for that to occur.
	 */
	private static RuntimeException failUnexpectedTestFileChange() {
		String msg = "Test file '" + ABNORMAL_SHARED_FORMULA_FLAG_TEST_FILE + "' has changed.  "
			+ "This junit may not be properly testing for the target bug.  "
			+ "Either revert the test file or ensure that the new version "
			+ "has the right characteristics to test the target bug.";
		// A breakpoint in ValueRecordsAggregate.handleMissingSharedFormulaRecord(FormulaRecord)
		// should get hit during parsing of Sheet1.
		// If the test spreadsheet is created as directed, this condition should occur.
		// It is easy to upset the test spreadsheet (for example re-saving will destroy the
		// peculiar condition we are testing for).
		throw new RuntimeException(msg);
	}

	/**
	 * gets a CRC checksum for the content of a file
	 */
	private static long getFileCRC(InputStream is) {
		CRC32 crc = new CRC32();
		byte[] buf = new byte[2048];
		try {
			while(true) {
				int bytesRead = is.read(buf);
				if(bytesRead < 1) {
					break;
				}
				crc.update(buf, 0, bytesRead);
			}
			is.close();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}

		return crc.getValue();
	}

    @Test
	void testRemoveNewRow_bug46312() throws IOException {
		// To make bug occur, rowIndex needs to be >= ValueRecordsAggregate.records.length
		int rowIndex = 30;

		ValueRecordsAggregate vra = new ValueRecordsAggregate();
		// bug 46312 - Specified rowIndex 30 is outside the allowable range (0..30)
		assertDoesNotThrow(() -> vra.removeAllCellsValuesForRow(rowIndex));

		// same bug as demonstrated through usermodel API
		try (HSSFWorkbook wb = new HSSFWorkbook()) {
			HSSFSheet sheet = wb.createSheet();
			HSSFRow row = sheet.createRow(rowIndex);

			// must not add any cells to the new row if we want to see the bug
			// row.createCell(0); // this causes ValueRecordsAggregate.records to auto-extend
			assertDoesNotThrow(() -> sheet.createRow(rowIndex));
		}
	}

	/**
	 * Tests various manipulations of blank cells, to make sure that {@link MulBlankRecord}s
	 * are use appropriately
	 */
    @Test
	void testMultipleBlanks() {
		BlankRecord brA2 = newBlankRecord(0, 1);
		BlankRecord brB2 = newBlankRecord(1, 1);
		BlankRecord brC2 = newBlankRecord(2, 1);
		BlankRecord brD2 = newBlankRecord(3, 1);
		BlankRecord brE2 = newBlankRecord(4, 1);
		BlankRecord brB3 = newBlankRecord(1, 2);
		BlankRecord brC3 = newBlankRecord(2, 2);

		valueRecord.insertCell(brA2);
		valueRecord.insertCell(brB2);
		valueRecord.insertCell(brD2);
		confirmMulBlank(3, 1, 1);

		valueRecord.insertCell(brC3);
		confirmMulBlank(4, 1, 2);

		valueRecord.insertCell(brB3);
		valueRecord.insertCell(brE2);
		confirmMulBlank(6, 3, 0);

		valueRecord.insertCell(brC2);
		confirmMulBlank(7, 2, 0);

		valueRecord.removeCell(brA2);
		confirmMulBlank(6, 2, 0);

		valueRecord.removeCell(brC2);
		confirmMulBlank(5, 2, 1);

		valueRecord.removeCell(brC3);
		confirmMulBlank(4, 1, 2);
	}

	private void confirmMulBlank(int expectedTotalBlankCells,
			int expectedNumberOfMulBlankRecords, int expectedNumberOfSingleBlankRecords) {
		// assumed row ranges set-up by caller:
		final int firstRow = 1;
		final int lastRow = 2;


		final class BlankStats {
			public int countBlankCells;
			public int countMulBlankRecords;
			public int countSingleBlankRecords;
		}

		final BlankStats bs = new BlankStats();
		RecordVisitor rv = r -> {
			if (r instanceof MulBlankRecord) {
				MulBlankRecord mbr = (MulBlankRecord) r;
				bs.countMulBlankRecords++;
				bs.countBlankCells += mbr.getNumColumns();
			} else if (r instanceof BlankRecord) {
				bs.countSingleBlankRecords++;
				bs.countBlankCells++;
			}
		};

		for (int rowIx = firstRow; rowIx <=lastRow; rowIx++) {
			if (valueRecord.rowHasCells(rowIx)) {
				valueRecord.visitCellsForRow(rowIx, rv);
			}
		}
		assertEquals(expectedTotalBlankCells, bs.countBlankCells);
		assertEquals(expectedNumberOfMulBlankRecords, bs.countMulBlankRecords);
		assertEquals(expectedNumberOfSingleBlankRecords, bs.countSingleBlankRecords);
	}
}
