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

import java.util.ArrayList;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.poi.ddf.DefaultEscherRecordFactory;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherRecordFactory;
import org.apache.poi.ddf.EscherRecordTypes;
import org.apache.poi.util.Internal;

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

/**
 * Information about drawings in the document.
 * <p>
 * The {@code delay stream} referenced in {@code [MS-ODRAW]} is the {@code WordDocument} stream.
 *
 * @author Squeeself
 */
@Internal
public final class OfficeArtContent {

	/**
	 * {@link EscherRecordTypes#DGG_CONTAINER} containing drawing group information for the document.
	 */
	private final EscherContainerRecord drawingGroupData = new EscherContainerRecord();

	/**
	 * {@link EscherRecordTypes#DG_CONTAINER} for drawings in the Main Document.
	 * <p>
	 * {@code null} to indicate that the document does not have a {@link EscherRecordTypes#DG_CONTAINER} for the Main
	 * Document.
	 */
	private EscherContainerRecord mainDocumentDgContainer;

	/**
	 * {@link EscherRecordTypes#DG_CONTAINER} for drawings in the Header Document.
	 * <p>
	 * {@code null} to indicate that the document does not have a {@link EscherRecordTypes#DG_CONTAINER} for the Header
	 * Document.
	 */
	private EscherContainerRecord headerDocumentDgContainer;

	public OfficeArtContent(byte[] data, int offset, int size) {
		fillEscherRecords(data, offset, size);
	}

	/**
	 * Parses the records out of the given data.
	 *
	 * The thing to be aware of here is that if {@code size} is {@code 0}, the document does not contain images.
	 *
	 * @see FileInformationBlock#getLcbDggInfo()
	 */
	private void fillEscherRecords(byte[] data, int offset, int size) {
		if (size == 0) return;

		EscherRecordFactory recordFactory = new DefaultEscherRecordFactory();
		int pos = offset;
		pos += drawingGroupData.fillFields(data, pos, recordFactory);
		assert drawingGroupData.getRecordId() == EscherRecordTypes.DGG_CONTAINER.typeID;

		/*
		 * After the drawingGroupData there is an array (2 slots max) that has data about drawings. According to the
		 * spec, the first slot is for the Main Document, the second for the Header Document. Additionally, the
		 * OfficeArtWordDrawing structure has a byte (dgglbl) that indicates whether the structure is for the Main or
		 * Header Document. In practice we've seen documents such as 61911.doc where the order of array entries does not
		 * match the dgglbl byte. As the byte is more likely to be reliable, we base the parsing off of that rather than
		 * array order.
		 */

		// This should loop at most twice
		while (pos < offset + size) {

			// Named this way to match section 2.9.172 of [MS-DOC] - v20191119.
			byte dgglbl = data[pos];
			assert dgglbl == 0x00 || dgglbl == 0x01;
			pos++;

			EscherContainerRecord dgContainer = new EscherContainerRecord();
			pos+= dgContainer.fillFields(data, pos, recordFactory);
			assert dgContainer.getRecordId() == EscherRecordTypes.DG_CONTAINER.typeID;

			switch (dgglbl) {
				case 0x00:
					mainDocumentDgContainer = dgContainer;
					break;
				case 0x01:
					headerDocumentDgContainer = dgContainer;
					break;
				default:
					LogManager.getLogger(OfficeArtContent.class).atWarn()
							.log("dgglbl {} for OfficeArtWordDrawing is out of bounds [0, 1]", box(dgglbl));
			}
		}

		assert pos == offset + size;
	}

    private List<? extends EscherContainerRecord> getDgContainers() {
        List<EscherContainerRecord> dgContainers = new ArrayList<>(2);
        if (mainDocumentDgContainer != null) {
            dgContainers.add(mainDocumentDgContainer);
        }
        if (headerDocumentDgContainer != null) {
            dgContainers.add(headerDocumentDgContainer);
        }
        return dgContainers;
    }

	/**
	 * @return The {@link EscherRecordTypes#BSTORE_CONTAINER} or {@code null} if the document doesn't have one.
	 */
	public EscherContainerRecord getBStoreContainer() {
    	return drawingGroupData.getChildById(EscherRecordTypes.BSTORE_CONTAINER.typeID);
    }

    public List<? extends EscherContainerRecord> getSpgrContainers()
    {
        List<EscherContainerRecord> spgrContainers = new ArrayList<>(
                1);
        for ( EscherContainerRecord dgContainer : getDgContainers() )
        {
            for ( EscherRecord escherRecord : dgContainer )
            {
                if ( escherRecord.getRecordId() == (short) 0xF003 )
                {
                    spgrContainers.add( (EscherContainerRecord) escherRecord );
                }
            }
        }
        return spgrContainers;
    }

    public List<? extends EscherContainerRecord> getSpContainers()
    {
        List<EscherContainerRecord> spContainers = new ArrayList<>(
                1);
        for ( EscherContainerRecord spgrContainer : getSpgrContainers() )
        {
            for ( EscherRecord escherRecord : spgrContainer )
            {
                if ( escherRecord.getRecordId() == (short) 0xF004 )
                {
                    spContainers.add( (EscherContainerRecord) escherRecord );
                }
            }
        }
        return spContainers;
    }

	@Override
	public String toString() {
		return "OfficeArtContent{" +
				"drawingGroupData=" + drawingGroupData +
				", mainDocumentDgContainer=" + mainDocumentDgContainer +
				", headerDocumentDgContainer=" + headerDocumentDgContainer +
				'}';
	}
}
