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

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.StringFormattedMessage;
import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.record.RecordTypes.RecordConstructor;
import org.apache.poi.util.LittleEndian;

import static org.apache.logging.log4j.util.Unbox.box;

/**
 * This abstract class represents a record in the PowerPoint document.
 * Record classes should extend with RecordContainer or RecordAtom, which
 *  extend this in turn.
 */

public abstract class Record implements GenericRecord
{
    // For logging
	protected static final Logger LOG = LogManager.getLogger(Record.class);

	/**
	 * Is this record type an Atom record (only has data),
	 *  or is it a non-Atom record (has other records)?
	 */
	public abstract boolean isAnAtom();

	/**
	 * Returns the type (held as a little endian in bytes 3 and 4)
	 *  that this class handles
	 */
	public abstract long getRecordType();

	/**
	 * Fetch all the child records of this record
	 * If this record is an atom, will return null
	 * If this record is a non-atom, but has no children, will return
	 *  an empty array
	 */
	public abstract Record[] getChildRecords();

	/**
	 * Have the contents printer out into an OutputStream, used when
	 *  writing a file back out to disk
	 * (Normally, atom classes will keep their bytes around, but
	 *  non atom classes will just request the bytes from their
	 *  children, then chuck on their header and return)
	 */
	public abstract void writeOut(OutputStream o) throws IOException;

	@Override
	public Enum getGenericRecordType() {
		return RecordTypes.forTypeID((int)getRecordType());
	}

	@Override
	public List<Record> getGenericChildren() {
		Record[] recs = getChildRecords();
		return (recs == null) ? null : Arrays.asList(recs);
	}

	/**
	 * When writing out, write out a signed int (32bit) in Little Endian format
	 */
	public static void writeLittleEndian(int i,OutputStream o) throws IOException {
		byte[] bi = new byte[4];
		LittleEndian.putInt(bi,0,i);
		o.write(bi);
	}
	/**
	 * When writing out, write out a signed short (16bit) in Little Endian format
	 */
	public static void writeLittleEndian(short s,OutputStream o) throws IOException {
		byte[] bs = new byte[2];
		LittleEndian.putShort(bs,0,s);
		o.write(bs);
	}

	/**
	 * Build and return the Record at the given offset.
	 * Note - does less error checking and handling than findChildRecords
	 * @param b The byte array to build from
	 * @param offset The offset to build at
	 */
	public static Record buildRecordAtOffset(byte[] b, int offset) {
		long type = LittleEndian.getUShort(b,offset+2);
		long rlen = LittleEndian.getUInt(b,offset+4);

		// Sanity check the length
		int rleni = (int)rlen;
		if(rleni < 0) { rleni = 0; }

		return createRecordForType(type,b,offset,8+rleni);
	}

	/**
	 * Default method for finding child records of a container record
	 */
	public static Record[] findChildRecords(byte[] b, int start, int len) {
		List<Record> children = new ArrayList<>(5);

		// Jump our little way along, creating records as we go
		int pos = start;
		while(pos <= (start+len-8)) {
			long type = LittleEndian.getUShort(b,pos+2);
			long rlen = LittleEndian.getUInt(b,pos+4);

			// Sanity check the length
			int rleni = (int)rlen;
			if(rleni < 0) { rleni = 0; }

			// Abort if first record is of type 0000 and length FFFF,
			//  as that's a sign of a screwed up record
			if(pos == 0 && type == 0L && rleni == 0xffff) {
				throw new CorruptPowerPointFileException("Corrupt document - starts with record of type 0000 and length 0xFFFF");
			}

			Record r = createRecordForType(type,b,pos,8+rleni);
			if(r != null) {
				children.add(r);
			}
			pos += 8;
			pos += rleni;
		}

		// Turn the vector into an array, and return
        return children.toArray(new Record[0]);
	}

	/**
	 * For a given type (little endian bytes 3 and 4 in record header),
	 *  byte array, start position and length:
	 *  will return a Record object that will handle that record
	 *
	 * Remember that while PPT stores the record lengths as 8 bytes short
	 *  (not including the size of the header), this code assumes you're
	 *  passing in corrected lengths
	 */
	public static Record createRecordForType(long type, byte[] b, int start, int len) {
		// We use the RecordTypes class to provide us with the right
		//  class to use for a given type
		// A spot of reflection gets us the (byte[],int,int) constructor
		// From there, we instanciate the class
		// Any special record handling occurs once we have the class
		RecordTypes recordType = RecordTypes.forTypeID((short) type);
		RecordConstructor c = recordType.recordConstructor;
		if (c == null) {
			// How odd. RecordTypes normally substitutes in
			//  a default handler class if it has heard of the record
			//  type but there's no support for it. Explicitly request
			//  that now
			LOG.atDebug().log(() -> new StringFormattedMessage("Known but unhandled record type %d (0x%04x) at offset %d", type, type, start));
			c = RecordTypes.UnknownRecordPlaceholder.recordConstructor;
		} else if (recordType == RecordTypes.UnknownRecordPlaceholder) {
			LOG.atDebug().log(() -> new StringFormattedMessage("Unknown placeholder type %d (0x%04x) at offset %d", type, type, start));
		}

		final Record toReturn;
		try {
			toReturn = c.apply(b, start, len);
		} catch(RuntimeException e) {
			// Handle case of a corrupt last record, whose claimed length
			//  would take us passed the end of the file
			if(start + len > b.length ) {
				LOG.atWarn().log("Warning: Skipping record of type {} at position {} which claims to be longer than the file! ({} vs {})", type, box(start), box(len), box(b.length - start));
				return null;
			}

			throw new HSLFException("Couldn't instantiate the class for type with id " + type + " on class " + c + " : " + e, e);
		}

		// Handling for special kinds of records follow

		// If it's a position aware record, tell it where it is
		if(toReturn instanceof PositionDependentRecord) {
			PositionDependentRecord pdr = (PositionDependentRecord)toReturn;
			pdr.setLastOnDiskOffset(start);
		}

		// Return the created record
		return toReturn;
	}


}
