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

import java.awt.Dimension;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.POIDocument;
import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.common.usermodel.fonts.FontInfo;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherOptRecord;
import org.apache.poi.hpsf.ClassID;
import org.apache.poi.hpsf.ClassIDPredefined;
import org.apache.poi.hpsf.DocumentSummaryInformation;
import org.apache.poi.hpsf.PropertySet;
import org.apache.poi.hpsf.SummaryInformation;
import org.apache.poi.hpsf.extractor.HPSFPropertiesExtractor;
import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.model.HeadersFooters;
import org.apache.poi.hslf.model.MovieShape;
import org.apache.poi.hslf.record.*;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.Ole10Native;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.sl.usermodel.MasterSheet;
import org.apache.poi.sl.usermodel.PictureData.PictureType;
import org.apache.poi.sl.usermodel.SlideShow;
import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;
import org.apache.poi.util.Units;

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

/**
 * This class is a friendly wrapper on top of the more scary HSLFSlideShow.
 *
 * TODO: - figure out how to match notes to their correct sheet (will involve
 * understanding DocSlideList and DocNotesList) - handle Slide creation cleaner
 */
public final class HSLFSlideShow extends POIDocument implements SlideShow<HSLFShape,HSLFTextParagraph>, Closeable, GenericRecord {

	/** Powerpoint document entry/stream name */
	public static final String POWERPOINT_DOCUMENT = "PowerPoint Document";
	public static final String PP97_DOCUMENT = "PP97_DUALSTORAGE";
	public static final String PP95_DOCUMENT = "PP40";

	// For logging
	private static final Logger LOG = LogManager.getLogger(HSLFSlideShow.class);

	//arbitrarily selected; may need to increase
	private static final int MAX_RECORD_LENGTH = 10_000_000;

    enum LoadSavePhase {
        INIT, LOADED
	}
    private static final ThreadLocal<LoadSavePhase> loadSavePhase = new ThreadLocal<>();

    // What we're based on
	private final HSLFSlideShowImpl _hslfSlideShow;

	// Pointers to the most recent versions of the core records
	// (Document, Notes, Slide etc)
	private Record[] _mostRecentCoreRecords;
	// Lookup between the PersitPtr "sheet" IDs, and the position
	// in the mostRecentCoreRecords array
	private Map<Integer,Integer> _sheetIdToCoreRecordsLookup;

	// Records that are interesting
	private Document _documentRecord;

	// Friendly objects for people to deal with
	private final List<HSLFSlideMaster> _masters = new ArrayList<>();
	private final List<HSLFTitleMaster> _titleMasters = new ArrayList<>();
	private final List<HSLFSlide> _slides = new ArrayList<>();
	private final List<HSLFNotes> _notes = new ArrayList<>();
	private FontCollection _fonts;


	/**
	 * Constructs a Powerpoint document from the underlying
	 * HSLFSlideShow object. Finds the model stuff from this
	 *
	 * @param hslfSlideShow the HSLFSlideShow to base on
	 */
	public HSLFSlideShow(HSLFSlideShowImpl hslfSlideShow) {
		super(hslfSlideShow.getDirectory());

	    loadSavePhase.set(LoadSavePhase.INIT);

	    // Get useful things from our base slideshow
	    _hslfSlideShow = hslfSlideShow;

		// Handle Parent-aware Records
		for (Record record : _hslfSlideShow.getRecords()) {
			if(record instanceof RecordContainer){
                RecordContainer.handleParentAwareRecords((RecordContainer)record);
            }
		}

		// Find the versions of the core records we'll want to use
		findMostRecentCoreRecords();

		// Build up the model level Slides and Notes
		buildSlidesAndNotes();

		loadSavePhase.set(LoadSavePhase.LOADED);
	}

	/**
	 * Constructs a new, empty, Powerpoint document.
	 */
	public HSLFSlideShow() {
		this(HSLFSlideShowImpl.create());
	}

	/**
	 * Constructs a Powerpoint document from an input stream.
	 */
	@SuppressWarnings("resource")
    public HSLFSlideShow(InputStream inputStream) throws IOException {
		this(new HSLFSlideShowImpl(inputStream));
	}

    /**
     * Constructs a Powerpoint document from an POIFSFileSystem.
     */
    @SuppressWarnings("resource")
    public HSLFSlideShow(POIFSFileSystem poifs) throws IOException {
        this(new HSLFSlideShowImpl(poifs));
    }

    /**
     * Constructs a Powerpoint document from an DirectoryNode.
     */
    @SuppressWarnings("resource")
    public HSLFSlideShow(DirectoryNode root) throws IOException {
        this(new HSLFSlideShowImpl(root));
    }

    /**
     * @return the current loading/saving phase
     */
    static LoadSavePhase getLoadSavePhase() {
        return loadSavePhase.get();
    }

	/**
	 * Use the PersistPtrHolder entries to figure out what is the "most recent"
	 * version of all the core records (Document, Notes, Slide etc), and save a
	 * record of them. Do this by walking from the oldest PersistPtr to the
	 * newest, overwriting any references found along the way with newer ones
	 */
	private void findMostRecentCoreRecords() {
		// To start with, find the most recent in the byte offset domain
		Map<Integer,Integer> mostRecentByBytes = new HashMap<>();
		for (Record record : _hslfSlideShow.getRecords()) {
			if (record instanceof PersistPtrHolder) {
				PersistPtrHolder pph = (PersistPtrHolder) record;

				// If we've already seen any of the "slide" IDs for this
				// PersistPtr, remove their old positions
				int[] ids = pph.getKnownSlideIDs();
				for (int id : ids) {
					mostRecentByBytes.remove(id);
				}

				// Now, update the byte level locations with their latest values
				Map<Integer,Integer> thisSetOfLocations = pph.getSlideLocationsLookup();
				for (int id : ids) {
					mostRecentByBytes.put(id, thisSetOfLocations.get(id));
				}
			}
		}

		// We now know how many unique special records we have, so init
		// the array
		_mostRecentCoreRecords = new Record[mostRecentByBytes.size()];

		// We'll also want to be able to turn the slide IDs into a position
		// in this array
		_sheetIdToCoreRecordsLookup = new HashMap<>();
		Integer[] allIDs = mostRecentByBytes.keySet().toArray(new Integer[0]);
		Arrays.sort(allIDs);
		for (int i = 0; i < allIDs.length; i++) {
			_sheetIdToCoreRecordsLookup.put(allIDs[i], i);
		}

		Map<Integer,Integer> mostRecentByBytesRev = new HashMap<>(mostRecentByBytes.size());
		for (Map.Entry<Integer,Integer> me : mostRecentByBytes.entrySet()) {
		    mostRecentByBytesRev.put(me.getValue(), me.getKey());
		}

		// Now convert the byte offsets back into record offsets
		for (Record record : _hslfSlideShow.getRecords()) {
			if (!(record instanceof PositionDependentRecord)) {
                continue;
            }

			PositionDependentRecord pdr = (PositionDependentRecord) record;
			int recordAt = pdr.getLastOnDiskOffset();

			Integer thisID = mostRecentByBytesRev.get(recordAt);

			if (thisID == null) {
                continue;
            }

			// Bingo. Now, where do we store it?
			int storeAt = _sheetIdToCoreRecordsLookup.get(thisID);

			// Tell it its Sheet ID, if it cares
			if (pdr instanceof PositionDependentRecordContainer) {
				PositionDependentRecordContainer pdrc = (PositionDependentRecordContainer) record;
				pdrc.setSheetId(thisID);
			}

			// Finally, save the record
			_mostRecentCoreRecords[storeAt] = record;
		}

		// Now look for the interesting records in there
		for (Record record : _mostRecentCoreRecords) {
			// Check there really is a record at this number
			if (record != null) {
				// Find the Document, and interesting things in it
				if (record.getRecordType() == RecordTypes.Document.typeID) {
					_documentRecord = (Document) record;
					_fonts = _documentRecord.getEnvironment().getFontCollection();
				}
			} /*else {
				// No record at this number
				// Odd, but not normally a problem
			}*/
		}
	}

	/**
	 * For a given SlideAtomsSet, return the core record, based on the refID
	 * from the SlidePersistAtom
	 */
	public Record getCoreRecordForSAS(SlideAtomsSet sas) {
		SlidePersistAtom spa = sas.getSlidePersistAtom();
		int refID = spa.getRefID();
		return getCoreRecordForRefID(refID);
	}

	/**
	 * For a given refID (the internal, 0 based numbering scheme), return the
	 * core record
	 *
	 * @param refID
	 *            the refID
	 */
	public Record getCoreRecordForRefID(int refID) {
		Integer coreRecordId = _sheetIdToCoreRecordsLookup.get(refID);
		if (coreRecordId != null) {
			return _mostRecentCoreRecords[coreRecordId];
		}
		LOG.atError().log("We tried to look up a reference to a core record, but there was no core ID for reference ID {}", box(refID));
		return null;
	}

	/**
	 * Build up model level Slide and Notes objects, from the underlying
	 * records.
	 */
	private void buildSlidesAndNotes() {
		// Ensure we really found a Document record earlier
		// If we didn't, then the file is probably corrupt
		if (_documentRecord == null) {
			throw new CorruptPowerPointFileException(
					"The PowerPoint file didn't contain a Document Record in its PersistPtr blocks. It is probably corrupt.");
		}

		// Fetch the SlideListWithTexts in the most up-to-date Document Record
		//
		// As far as we understand it:
		// * The first SlideListWithText will contain a SlideAtomsSet
		// for each of the master slides
		// * The second SlideListWithText will contain a SlideAtomsSet
		// for each of the slides, in their current order
		// These SlideAtomsSets will normally contain text
		// * The third SlideListWithText (if present), will contain a
		// SlideAtomsSet for each Notes
		// These SlideAtomsSets will not normally contain text
		//
		// Having indentified the masters, slides and notes + their orders,
		// we have to go and find their matching records
		// We always use the latest versions of these records, and use the
		// SlideAtom/NotesAtom to match them with the StyleAtomSet

		findMasterSlides();

		// Having sorted out the masters, that leaves the notes and slides
        Map<Integer,Integer> slideIdToNotes = new HashMap<>();

        // Start by finding the notes records
        findNotesSlides(slideIdToNotes);

		// Now, do the same thing for our slides
		findSlides(slideIdToNotes);
	}

	/**
     * Find master slides
     * These can be MainMaster records, but oddly they can also be
     * Slides or Notes, and possibly even other odd stuff....
     * About the only thing you can say is that the master details are in the first SLWT.
	 */
	private void findMasterSlides() {
        SlideListWithText masterSLWT = _documentRecord.getMasterSlideListWithText();
        if (masterSLWT == null) {
            return;
        }

        for (SlideAtomsSet sas : masterSLWT.getSlideAtomsSets()) {
            Record r = getCoreRecordForSAS(sas);
            int sheetNo = sas.getSlidePersistAtom().getSlideIdentifier();
            if (r instanceof Slide) {
                HSLFTitleMaster master = new HSLFTitleMaster((Slide)r, sheetNo);
                master.setSlideShow(this);
                _titleMasters.add(master);
            } else if (r instanceof MainMaster) {
                HSLFSlideMaster master = new HSLFSlideMaster((MainMaster)r, sheetNo);
                master.setSlideShow(this);
                _masters.add(master);
            }
        }
	}

	private void findNotesSlides(Map<Integer,Integer> slideIdToNotes) {
        SlideListWithText notesSLWT = _documentRecord.getNotesSlideListWithText();

        if (notesSLWT == null) {
            return;
        }

        // Match up the records and the SlideAtomSets
        int idx = -1;
        for (SlideAtomsSet notesSet : notesSLWT.getSlideAtomsSets()) {
            idx++;
            // Get the right core record
            Record r = getCoreRecordForSAS(notesSet);
            SlidePersistAtom spa = notesSet.getSlidePersistAtom();

            String loggerLoc = "A Notes SlideAtomSet at "+idx+" said its record was at refID "+spa.getRefID();

            // we need to add null-records, otherwise the index references to other existing don't work anymore
            if (r == null) {
				LOG.atWarn().log("{}, but that record didn't exist - record ignored.", loggerLoc);
                continue;
            }

            // Ensure it really is a notes record
            if (!(r instanceof Notes)) {
				LOG.atError().log("{}, but that was actually a {}", loggerLoc, r);
                continue;
            }

            Notes notesRecord = (Notes) r;

            // Record the match between slide id and these notes
            int slideId = spa.getSlideIdentifier();
            slideIdToNotes.put(slideId, idx);

            HSLFNotes hn = new HSLFNotes(notesRecord);
            hn.setSlideShow(this);
            _notes.add(hn);
        }
	}

	private void findSlides(Map<Integer,Integer> slideIdToNotes) {
        SlideListWithText slidesSLWT = _documentRecord.getSlideSlideListWithText();
        if (slidesSLWT == null) {
            return;
        }

        // Match up the records and the SlideAtomSets
        int idx = -1;
        for (SlideAtomsSet sas : slidesSLWT.getSlideAtomsSets()) {
            idx++;
            // Get the right core record
            SlidePersistAtom spa = sas.getSlidePersistAtom();
            Record r = getCoreRecordForSAS(sas);

            // Ensure it really is a slide record
            if (!(r instanceof Slide)) {
				LOG.atError().log("A Slide SlideAtomSet at {} said its record was at refID {}, but that was actually a {}", box(idx),box(spa.getRefID()),r);
                continue;
            }

            Slide slide = (Slide)r;

            // Do we have a notes for this?
            HSLFNotes notes = null;
            // Slide.SlideAtom.notesId references the corresponding notes slide.
            // 0 if slide has no notes.
            int noteId = slide.getSlideAtom().getNotesID();
            if (noteId != 0) {
                Integer notesPos = slideIdToNotes.get(noteId);
                if (notesPos != null && 0 <= notesPos && notesPos < _notes.size()) {
                    notes = _notes.get(notesPos);
                } else {
                    LOG.atError().log("Notes not found for noteId={}", box(noteId));
                }
            }

            // Now, build our slide
            int slideIdentifier = spa.getSlideIdentifier();
            HSLFSlide hs = new HSLFSlide(slide, notes, sas, slideIdentifier, (idx + 1));
            hs.setSlideShow(this);
            _slides.add(hs);
        }
	}

	@Override
	public void write(OutputStream out) throws IOException {
	    // check for text paragraph modifications
	    for (HSLFSlide sl : getSlides()) {
	        writeDirtyParagraphs(sl);
	    }

	    for (HSLFSlideMaster sl : getSlideMasters()) {
	        boolean isDirty = false;
	        for (List<HSLFTextParagraph> paras : sl.getTextParagraphs()) {
	            for (HSLFTextParagraph p : paras) {
	                isDirty |= p.isDirty();
	            }
	        }
	        if (isDirty) {
	            for (TxMasterStyleAtom sa : sl.getTxMasterStyleAtoms()) {
	                if (sa != null) {
	                    // not all master style atoms are set - index 3 is typically null
	                    sa.updateStyles();
	                }
	            }
	        }
	    }

		_hslfSlideShow.write(out);
	}

	private void writeDirtyParagraphs(HSLFShapeContainer container) {
        for (HSLFShape sh : container.getShapes()) {
            if (sh instanceof HSLFShapeContainer) {
                writeDirtyParagraphs((HSLFShapeContainer)sh);
            } else if (sh instanceof HSLFTextShape) {
                HSLFTextShape hts = (HSLFTextShape)sh;
                boolean isDirty = false;
                for (HSLFTextParagraph p : hts.getTextParagraphs()) {
                    isDirty |= p.isDirty();
                }
                if (isDirty) {
                    hts.storeText();
                }
            }
        }
	}

	/**
	 * Returns an array of the most recent version of all the interesting
	 * records
	 */
	public Record[] getMostRecentCoreRecords() {
		return _mostRecentCoreRecords;
	}

	/**
	 * Returns an array of all the normal Slides found in the slideshow
	 */
	@Override
	public List<HSLFSlide> getSlides() {
		return _slides;
	}

	/**
	 * Returns an array of all the normal Notes found in the slideshow
	 */
	public List<HSLFNotes> getNotes() {
		return _notes;
	}

	/**
	 * Returns an array of all the normal Slide Masters found in the slideshow
	 */
	@Override
	public List<HSLFSlideMaster> getSlideMasters() {
		return _masters;
	}

	/**
	 * Returns an array of all the normal Title Masters found in the slideshow
	 */
	public List<HSLFTitleMaster> getTitleMasters() {
		return _titleMasters;
	}

	@Override
	public List<HSLFPictureData> getPictureData() {
		return _hslfSlideShow.getPictureData();
	}

	/**
	 * Returns the data of all the embedded OLE object in the SlideShow
	 */
	@SuppressWarnings("WeakerAccess")
	public HSLFObjectData[] getEmbeddedObjects() {
		return _hslfSlideShow.getEmbeddedObjects();
	}

	/**
	 * Returns the data of all the embedded sounds in the SlideShow
	 */
	public HSLFSoundData[] getSoundData() {
		return HSLFSoundData.find(_documentRecord);
	}

	@Override
	public Dimension getPageSize() {
		DocumentAtom docatom = _documentRecord.getDocumentAtom();
		int pgx = (int)Units.masterToPoints((int)docatom.getSlideSizeX());
		int pgy = (int)Units.masterToPoints((int)docatom.getSlideSizeY());
		return new Dimension(pgx, pgy);
	}

	@Override
	public void setPageSize(Dimension pgsize) {
		DocumentAtom docatom = _documentRecord.getDocumentAtom();
		docatom.setSlideSizeX(Units.pointsToMaster(pgsize.width));
		docatom.setSlideSizeY(Units.pointsToMaster(pgsize.height));
	}

	/**
	 * Helper method for usermodel: Get the font collection
	 */
	FontCollection getFontCollection() {
		return _fonts;
	}

	/**
	 * Helper method for usermodel and model: Get the document record
	 */
	public Document getDocumentRecord() {
		return _documentRecord;
	}

	/**
	 * Re-orders a slide, to a new position.
	 *
	 * @param oldSlideNumber
	 *            The old slide number (1 based)
	 * @param newSlideNumber
	 *            The new slide number (1 based)
	 */
	@SuppressWarnings("WeakerAccess")
	public void reorderSlide(int oldSlideNumber, int newSlideNumber) {
		// Ensure these numbers are valid
		if (oldSlideNumber < 1 || newSlideNumber < 1) {
			throw new IllegalArgumentException("Old and new slide numbers must be greater than 0");
		}
		if (oldSlideNumber > _slides.size() || newSlideNumber > _slides.size()) {
			throw new IllegalArgumentException(
					"Old and new slide numbers must not exceed the number of slides ("
							+ _slides.size() + ")");
		}

		// The order of slides is defined by the order of slide atom sets in the
		// SlideListWithText container.
		SlideListWithText slwt = _documentRecord.getSlideSlideListWithText();
		if (slwt == null) {
			throw new IllegalStateException("Slide record not defined.");
		}
		SlideAtomsSet[] sas = slwt.getSlideAtomsSets();

		SlideAtomsSet tmp = sas[oldSlideNumber - 1];
		sas[oldSlideNumber - 1] = sas[newSlideNumber - 1];
		sas[newSlideNumber - 1] = tmp;

		Collections.swap(_slides, oldSlideNumber - 1, newSlideNumber - 1);
		_slides.get(newSlideNumber - 1).setSlideNumber(newSlideNumber);
		_slides.get(oldSlideNumber - 1).setSlideNumber(oldSlideNumber);

		ArrayList<Record> lst = new ArrayList<>();
		for (SlideAtomsSet s : sas) {
			lst.add(s.getSlidePersistAtom());
			lst.addAll(Arrays.asList(s.getSlideRecords()));
		}

		Record[] r = lst.toArray(new Record[0]);
		slwt.setChildRecord(r);
	}

	/**
	 * Removes the slide at the given index (0-based).
	 * <p>
	 * Shifts any subsequent slides to the left (subtracts one from their slide
	 * numbers).
	 * </p>
	 *
	 * @param index
	 *            the index of the slide to remove (0-based)
	 * @return the slide that was removed from the slide show.
	 */
	@SuppressWarnings("WeakerAccess")
	public HSLFSlide removeSlide(int index) {
		int lastSlideIdx = _slides.size() - 1;
		if (index < 0 || index > lastSlideIdx) {
			throw new IllegalArgumentException("Slide index (" + index + ") is out of range (0.."
					+ lastSlideIdx + ")");
		}

		SlideListWithText slwt = _documentRecord.getSlideSlideListWithText();
		if (slwt == null) {
			throw new IllegalStateException("Slide record not defined.");
		}
		SlideAtomsSet[] sas = slwt.getSlideAtomsSets();

		List<Record> records = new ArrayList<>();
		List<SlideAtomsSet> sa = new ArrayList<>(Arrays.asList(sas));

		HSLFSlide removedSlide = _slides.remove(index);
		_notes.remove(removedSlide.getNotes());
		sa.remove(index);

		int i=0;
		for (HSLFSlide s : _slides) {
            s.setSlideNumber(i++);
        }

		for (SlideAtomsSet s : sa) {
            records.add(s.getSlidePersistAtom());
            records.addAll(Arrays.asList(s.getSlideRecords()));
		}
		if (sa.isEmpty()) {
			_documentRecord.removeSlideListWithText(slwt);
		} else {
			slwt.setSlideAtomsSets(sa.toArray(new SlideAtomsSet[0]));
			slwt.setChildRecord(records.toArray(new Record[0]));
		}

		// if the removed slide had notes - remove references to them too

        int notesId = removedSlide.getSlideRecord().getSlideAtom().getNotesID();
		if (notesId != 0) {
			SlideListWithText nslwt = _documentRecord.getNotesSlideListWithText();
			records = new ArrayList<>();
			ArrayList<SlideAtomsSet> na = new ArrayList<>();
			if (nslwt != null) {
				for (SlideAtomsSet ns : nslwt.getSlideAtomsSets()) {
					if (ns.getSlidePersistAtom().getSlideIdentifier() == notesId) {
						continue;
					}
					na.add(ns);
					records.add(ns.getSlidePersistAtom());
					if (ns.getSlideRecords() != null) {
						records.addAll(Arrays.asList(ns.getSlideRecords()));
					}
				}

				if (!na.isEmpty()) {
					nslwt.setSlideAtomsSets(na.toArray(new SlideAtomsSet[0]));
					nslwt.setChildRecord(records.toArray(new Record[0]));
				}
			}
			if (na.isEmpty()) {
				_documentRecord.removeSlideListWithText(nslwt);
			}
		}

		return removedSlide;
	}

	/**
	 * Create a blank <code>Slide</code>.
	 *
	 * @return the created <code>Slide</code>
	 */
	@Override
	public HSLFSlide createSlide() {
		// We need to add the records to the SLWT that deals
		// with Slides.
		// Add it, if it doesn't exist
		SlideListWithText slist = _documentRecord.getSlideSlideListWithText();
		if (slist == null) {
			// Need to add a new one
			slist = new SlideListWithText();
			slist.setInstance(SlideListWithText.SLIDES);
			_documentRecord.addSlideListWithText(slist);
		}

		// Grab the SlidePersistAtom with the highest Slide Number.
		// (Will stay as null if no SlidePersistAtom exists yet in
		// the slide, or only master slide's ones do)
		SlidePersistAtom prev = null;
		for (SlideAtomsSet sas : slist.getSlideAtomsSets()) {
			SlidePersistAtom spa = sas.getSlidePersistAtom();
			if (spa.getSlideIdentifier() >= 0) {
				// Must be for a real slide
				if (prev == null) {
					prev = spa;
				}
				if (prev.getSlideIdentifier() < spa.getSlideIdentifier()) {
					prev = spa;
				}
			}
		}

		// Set up a new SlidePersistAtom for this slide
		SlidePersistAtom sp = new SlidePersistAtom();

		// First slideId is always 256
		sp.setSlideIdentifier(prev == null ? 256 : (prev.getSlideIdentifier() + 1));

		// Add this new SlidePersistAtom to the SlideListWithText
		slist.addSlidePersistAtom(sp);

		// Create a new Slide
		HSLFSlide slide = new HSLFSlide(sp.getSlideIdentifier(), sp.getRefID(), _slides.size() + 1);
		slide.setSlideShow(this);
		slide.onCreate();

		// Add in to the list of Slides
		_slides.add(slide);
		LOG.atInfo().log("Added slide {} with ref {} and identifier {}", box(_slides.size()),box(sp.getRefID()),box(sp.getSlideIdentifier()));

		// Add the core records for this new Slide to the record tree
		Slide slideRecord = slide.getSlideRecord();
		int psrId = addPersistentObject(slideRecord);
		sp.setRefID(psrId);
		slideRecord.setSheetId(psrId);

		slide.setMasterSheet(_masters.get(0));
		// All done and added
		return slide;
	}

	@Override
	public HSLFPictureData addPicture(byte[] data, PictureType format) throws IOException {
		if (format == null || format.nativeId == -1) {
			throw new IllegalArgumentException("Unsupported picture format: " + format);
		}

		HSLFPictureData pd = findPictureData(data);
		if (pd != null) {
			// identical picture was already added to the SlideShow
			return pd;
		}

		EscherContainerRecord bstore;

		EscherContainerRecord dggContainer = _documentRecord.getPPDrawingGroup().getDggContainer();
		bstore = HSLFShape.getEscherChild(dggContainer,
				EscherContainerRecord.BSTORE_CONTAINER);
		if (bstore == null) {
			bstore = new EscherContainerRecord();
			bstore.setRecordId(EscherContainerRecord.BSTORE_CONTAINER);

			dggContainer.addChildBefore(bstore, EscherOptRecord.RECORD_ID);
		}

		EscherBSERecord bse = addNewEscherBseRecord(bstore, format, data, 0);
		HSLFPictureData pict = HSLFPictureData.createFromImageData(format, bstore, bse, data);

		int offset = _hslfSlideShow.addPicture(pict);
		bse.setOffset(offset);

		return pict;
	}

	/**
	 * Adds a picture to the presentation.
	 *
	 * @param is	        The stream to read the image from
	 * @param format        The format of the picture.
	 *
	 * @return the picture data.
	 * @since 3.15 beta 2
	 */
	@Override
	public HSLFPictureData addPicture(InputStream is, PictureType format) throws IOException {
	    if (format == null || format.nativeId == -1) { // fail early
	        throw new IllegalArgumentException("Unsupported picture format: " + format);
	    }
	    return addPicture(IOUtils.toByteArray(is), format);
	}

	/**
	 * Adds a picture to the presentation.
	 *
	 * @param pict
	 *            the file containing the image to add
	 * @param format
	 *            The format of the picture.
	 *
	 * @return the picture data.
	 * @since 3.15 beta 2
	 */
	@Override
	public HSLFPictureData addPicture(File pict, PictureType format) throws IOException {
	    if (format == null || format.nativeId == -1) { // fail early
	        throw new IllegalArgumentException("Unsupported picture format: " + format);
	    }
		byte[] data = IOUtils.safelyAllocate(pict.length(), MAX_RECORD_LENGTH);
		try (FileInputStream is = new FileInputStream(pict)) {
			IOUtils.readFully(is, data);
		}
		return addPicture(data, format);
	}

    /**
     * check if a picture with this picture data already exists in this presentation
     *
     * @param pictureData The picture data to find in the SlideShow
     * @return {@code null} if picture data is not found in this slideshow
     * @since 3.15 beta 3
     */
    @Override
    public HSLFPictureData findPictureData(byte[] pictureData) {
        byte[] uid = HSLFPictureData.getChecksum(pictureData);

        for (HSLFPictureData pic : getPictureData()) {
            if (Arrays.equals(pic.getUID(), uid)) {
                return pic;
            }
        }
        return null;
    }

	/**
	 * Add a font in this presentation
	 *
	 * @param fontInfo the font to add
	 * @return the registered HSLFFontInfo - the font info object is unique based on the typeface
	 */
	public HSLFFontInfo addFont(FontInfo fontInfo) {
		return getDocumentRecord().getEnvironment().getFontCollection().addFont(fontInfo);
	}

	/**
	 * Add a font in this presentation and also embed its font data
	 *
	 * @param fontData the EOT font data as stream
	 *
	 * @return the registered HSLFFontInfo - the font info object is unique based on the typeface
	 *
	 * @since POI 4.1.0
	 */
	public HSLFFontInfo addFont(InputStream fontData) throws IOException {
		Document doc = getDocumentRecord();
		doc.getDocumentAtom().setSaveWithFonts(true);
		return doc.getEnvironment().getFontCollection().addFont(fontData);
	}

	/**
	 * Get a font by index
	 *
	 * @param idx
	 *            0-based index of the font
	 * @return of an instance of <code>PPFont</code> or <code>null</code> if not
	 *         found
	 */
	public HSLFFontInfo getFont(int idx) {
	    return getDocumentRecord().getEnvironment().getFontCollection().getFontInfo(idx);
	}

	/**
	 * get the number of fonts in the presentation
	 *
	 * @return number of fonts
	 */
	public int getNumberOfFonts() {
		return getDocumentRecord().getEnvironment().getFontCollection().getNumberOfFonts();
	}

	@Override
	public List<HSLFFontInfo> getFonts() {
		return getDocumentRecord().getEnvironment().getFontCollection().getFonts();
	}

	/**
	 * Return Header / Footer settings for slides
	 *
	 * @return Header / Footer settings for slides
	 */
	public HeadersFooters getSlideHeadersFooters() {
		return new HeadersFooters(this, HeadersFootersContainer.SlideHeadersFootersContainer);
	}

	/**
	 * Return Header / Footer settings for notes
	 *
	 * @return Header / Footer settings for notes
	 */
	public HeadersFooters getNotesHeadersFooters() {
	    if (_notes.isEmpty()) {
	        return new HeadersFooters(this, HeadersFootersContainer.NotesHeadersFootersContainer);
	    } else {
	        return new HeadersFooters(_notes.get(0), HeadersFootersContainer.NotesHeadersFootersContainer);
	    }
	}

	/**
	 * Add a movie in this presentation
	 *
	 * @param path
	 *            the path or url to the movie
	 * @return 0-based index of the movie
	 */
	public int addMovie(String path, int type) {
		ExMCIMovie mci;
		switch (type) {
			case MovieShape.MOVIE_MPEG:
				mci = new ExMCIMovie();
				break;
			case MovieShape.MOVIE_AVI:
				mci = new ExAviMovie();
				break;
			default:
				throw new IllegalArgumentException("Unsupported Movie: " + type);
		}

		ExVideoContainer exVideo = mci.getExVideo();
		exVideo.getExMediaAtom().setMask(0xE80000);
		exVideo.getPathAtom().setText(path);

		int objectId = addToObjListAtom(mci);
		exVideo.getExMediaAtom().setObjectId(objectId);

		return objectId;
	}

	/**
	 * Add a control in this presentation
	 *
	 * @param name
	 *            name of the control, e.g. "Shockwave Flash Object"
	 * @param progId
	 *            OLE Programmatic Identifier, e.g.
	 *            "ShockwaveFlash.ShockwaveFlash.9"
	 * @return 0-based index of the control
	 */
	@SuppressWarnings("unused")
	public int addControl(String name, String progId) {
		ExControl ctrl = new ExControl();
		ctrl.setProgId(progId);
		ctrl.setMenuName(name);
		ctrl.setClipboardName(name);

		ExOleObjAtom oleObj = ctrl.getExOleObjAtom();
		oleObj.setDrawAspect(ExOleObjAtom.DRAW_ASPECT_VISIBLE);
		oleObj.setType(ExOleObjAtom.TYPE_CONTROL);
		oleObj.setSubType(ExOleObjAtom.SUBTYPE_DEFAULT);

		int objectId = addToObjListAtom(ctrl);
		oleObj.setObjID(objectId);
		return objectId;
	}

	/**
	 * Add a embedded object to this presentation
	 *
	 * @return 0-based index of the embedded object
	 */
	public int addEmbed(POIFSFileSystem poiData) {
        DirectoryNode root = poiData.getRoot();

        // prepare embedded data
        if (new ClassID().equals(root.getStorageClsid())) {
        	// need to set class id
	        Map<String,ClassID> olemap = getOleMap();
	        ClassID classID = null;
	    	for (Map.Entry<String,ClassID> entry : olemap.entrySet()) {
	    		if (root.hasEntry(entry.getKey())) {
	    			classID = entry.getValue();
	    			break;
	    		}
	    	}
	    	if (classID == null) {
	    		throw new IllegalArgumentException("Unsupported embedded document");
	    	}

	    	root.setStorageClsid(classID);
        }

		ExEmbed exEmbed = new ExEmbed();
        // remove unneccessary infos, so we don't need to specify the type
        // of the ole object multiple times
        Record[] children = exEmbed.getChildRecords();
        exEmbed.removeChild(children[2]);
        exEmbed.removeChild(children[3]);
        exEmbed.removeChild(children[4]);

        ExEmbedAtom eeEmbed = exEmbed.getExEmbedAtom();
        eeEmbed.setCantLockServerB(true);

        ExOleObjAtom eeAtom = exEmbed.getExOleObjAtom();
        eeAtom.setDrawAspect(ExOleObjAtom.DRAW_ASPECT_VISIBLE);
        eeAtom.setType(ExOleObjAtom.TYPE_EMBEDDED);
        // eeAtom.setSubType(ExOleObjAtom.SUBTYPE_EXCEL);
        // should be ignored?!?, see MS-PPT ExOleObjAtom, but Libre Office sets it ...
        eeAtom.setOptions(1226240);

        ExOleObjStg exOleObjStg = new ExOleObjStg();
        try {
            Ole10Native.createOleMarkerEntry(poiData);
	        ByteArrayOutputStream bos = new ByteArrayOutputStream();
	        poiData.writeFilesystem(bos);
	        exOleObjStg.setData(bos.toByteArray());
        } catch (IOException e) {
        	throw new HSLFException(e);
        }

        int psrId = addPersistentObject(exOleObjStg);
        exOleObjStg.setPersistId(psrId);
        eeAtom.setObjStgDataRef(psrId);

		int objectId = addToObjListAtom(exEmbed);
		eeAtom.setObjID(objectId);
		return objectId;
	}

	@Override
    public HPSFPropertiesExtractor getMetadataTextExtractor() {
        return new HPSFPropertiesExtractor(getSlideShowImpl());
    }

	int addToObjListAtom(RecordContainer exObj) {
		ExObjList lst = getDocumentRecord().getExObjList(true);
		ExObjListAtom objAtom = lst.getExObjListAtom();
		// increment the object ID seed
		int objectId = (int) objAtom.getObjectIDSeed() + 1;
		objAtom.setObjectIDSeed(objectId);

		lst.addChildAfter(exObj, objAtom);

		return objectId;
	}

    private static Map<String,ClassID> getOleMap() {
    	Map<String,ClassID> olemap = new HashMap<>();
    	olemap.put(POWERPOINT_DOCUMENT, ClassIDPredefined.POWERPOINT_V8.getClassID());
    	// as per BIFF8 spec
    	olemap.put("Workbook", ClassIDPredefined.EXCEL_V8.getClassID());
    	// Typically from third party programs
    	olemap.put("WORKBOOK", ClassIDPredefined.EXCEL_V8.getClassID());
    	// Typically odd Crystal Reports exports
    	olemap.put("BOOK", ClassIDPredefined.EXCEL_V8.getClassID());
    	// ... to be continued
    	return olemap;
    }

    private int addPersistentObject(PositionDependentRecord slideRecord) {
    	slideRecord.setLastOnDiskOffset(HSLFSlideShowImpl.UNSET_OFFSET);
		_hslfSlideShow.appendRootLevelRecord((Record)slideRecord);

        // For position dependent records, hold where they were and now are
        // As we go along, update, and hand over, to any Position Dependent
        // records we happen across
		Map<RecordTypes,PositionDependentRecord> interestingRecords =
                new HashMap<>();

		try {
            _hslfSlideShow.updateAndWriteDependantRecords(null,interestingRecords);
        } catch (IOException e) {
            throw new HSLFException(e);
        }

		PersistPtrHolder ptr = (PersistPtrHolder)interestingRecords.get(RecordTypes.PersistPtrIncrementalBlock);
		UserEditAtom usr = (UserEditAtom)interestingRecords.get(RecordTypes.UserEditAtom);

		// persist ID is UserEditAtom.maxPersistWritten + 1
		int psrId = usr.getMaxPersistWritten() + 1;

		// Last view is now of the slide
		usr.setLastViewType((short) UserEditAtom.LAST_VIEW_SLIDE_VIEW);
		// increment the number of persistent objects
		usr.setMaxPersistWritten(psrId);

		// Add the new slide into the last PersistPtr
		// (Also need to tell it where it is)
		int slideOffset = slideRecord.getLastOnDiskOffset();
		slideRecord.setLastOnDiskOffset(slideOffset);
		ptr.addSlideLookup(psrId, slideOffset);
		LOG.atInfo().log("New slide/object ended up at {}", box(slideOffset));

		return psrId;
    }

    @Override
    public MasterSheet<HSLFShape,HSLFTextParagraph> createMasterSheet() {
		// TODO implement or throw exception if not supported
        return null;
    }

    /**
     * @return the handler class which holds the hslf records
     */
    @Internal
    public HSLFSlideShowImpl getSlideShowImpl() {
        return _hslfSlideShow;
    }

    @Override
    public void close() throws IOException {
        _hslfSlideShow.close();
    }

	@Override
	public Object getPersistDocument() {
		return getSlideShowImpl();
	}

	@Override
	public Map<String, Supplier<?>> getGenericProperties() {
		return GenericRecordUtil.getGenericProperties(
			"pictures", this::getPictureData,
			"embeddedObjects", this::getEmbeddedObjects
		);
	}

	@Override
	public List<? extends GenericRecord> getGenericChildren() {
		return Arrays.asList(_hslfSlideShow.getRecords());
	}

	@Override
	public void write() throws IOException {
		getSlideShowImpl().write();
	}

	@Override
	public void write(File newFile) throws IOException {
		getSlideShowImpl().write(newFile);
	}

	@Override
	public DocumentSummaryInformation getDocumentSummaryInformation() {
		return getSlideShowImpl().getDocumentSummaryInformation();
	}

	@Override
	public SummaryInformation getSummaryInformation() {
		return getSlideShowImpl().getSummaryInformation();
	}

	@Override
	public void createInformationProperties() {
		getSlideShowImpl().createInformationProperties();
	}

	@Override
	public void readProperties() {
		getSlideShowImpl().readProperties();
	}

	@Override
	protected PropertySet getPropertySet(String setName) throws IOException {
		return getSlideShowImpl().getPropertySetImpl(setName);
	}

	@Override
	protected PropertySet getPropertySet(String setName, EncryptionInfo encryptionInfo) throws IOException {
		return getSlideShowImpl().getPropertySetImpl(setName, encryptionInfo);
	}

	@Override
	protected void writeProperties() throws IOException {
		getSlideShowImpl().writePropertiesImpl();
	}

	@Override
	public void writeProperties(POIFSFileSystem outFS) throws IOException {
		getSlideShowImpl().writeProperties(outFS);
	}

	@Override
	protected void writeProperties(POIFSFileSystem outFS, List<String> writtenEntries) throws IOException {
		getSlideShowImpl().writePropertiesImpl(outFS, writtenEntries);
	}

	@Override
	protected void validateInPlaceWritePossible() throws IllegalStateException {
		getSlideShowImpl().validateInPlaceWritePossibleImpl();
	}

	@Override
	public DirectoryNode getDirectory() {
		return getSlideShowImpl().getDirectory();
	}

	@Override
	protected void clearDirectory() {
		getSlideShowImpl().clearDirectoryImpl();
	}

	@Override
	protected boolean initDirectory() {
		return getSlideShowImpl().initDirectoryImpl();
	}

	@Override
	protected void replaceDirectory(DirectoryNode newDirectory) throws IOException {
		getSlideShowImpl().replaceDirectoryImpl(newDirectory);
	}

	@Override
	protected String getEncryptedPropertyStreamName() {
		return getSlideShowImpl().getEncryptedPropertyStreamName();
	}

	@Override
	public EncryptionInfo getEncryptionInfo() throws IOException {
		return getSlideShowImpl().getEncryptionInfo();
	}

	static EscherBSERecord addNewEscherBseRecord(EscherContainerRecord blipStore, PictureType type, byte[] imageData, int offset) {
		EscherBSERecord record = new EscherBSERecord();
		record.setRecordId(EscherBSERecord.RECORD_ID);
		record.setOptions((short) (0x0002 | (type.nativeId << 4)));
		record.setSize(imageData.length + HSLFPictureData.PREAMBLE_SIZE);
		record.setUid(Arrays.copyOf(imageData, HSLFPictureData.CHECKSUM_SIZE));

		record.setBlipTypeMacOS((byte) type.nativeId);
		record.setBlipTypeWin32((byte) type.nativeId);

		if (type == PictureType.EMF) {
			record.setBlipTypeMacOS((byte) PictureType.PICT.nativeId);
		} else if (type == PictureType.WMF) {
			record.setBlipTypeMacOS((byte) PictureType.PICT.nativeId);
		} else if (type == PictureType.PICT) {
			record.setBlipTypeWin32((byte) PictureType.WMF.nativeId);
		}

		record.setOffset(offset);

		blipStore.addChildRecord(record);
		int count = blipStore.getChildCount();
		blipStore.setOptions((short) ((count << 4) | 0xF));

		return record;
	}
}
