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

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LocaleUtil;

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

/**
 * Factor class to create the appropriate chunks, which
 *  needs the version of the file to process the chunk header
 *  and trailer areas.
 * Makes use of chunks_parse_cmds.tbl from vsdump to be able
 *  to process the chunk value area
 */
public final class ChunkFactory {

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


	/** The version of the currently open document */
	private int version;
	/**
	 * Key is a Chunk's type, value is an array of its CommandDefinitions
	 */
	private final Map<Integer, CommandDefinition[]> chunkCommandDefinitions =
            new HashMap<>();
	/**
	 * What the name is of the chunk table definitions file?
	 * This file comes from the scratchpad resources directory.
	 */
	private static final String chunkTableName =
		"/org/apache/poi/hdgf/chunks_parse_cmds.tbl";

	/** For logging problems we spot with the file */
	private static final Logger LOG = LogManager.getLogger(ChunkFactory.class);

	public ChunkFactory(int version) throws IOException {
		this.version = version;

		processChunkParseCommands();
	}

	/**
	 * Open chunks_parse_cmds.tbl and process it, to get the definitions
	 *  of all the different possible chunk commands.
	 */
	private void processChunkParseCommands() throws IOException {
		try (InputStream cpd = ChunkFactory.class.getResourceAsStream(chunkTableName)) {
	        if(cpd == null) {
	            throw new IllegalStateException("Unable to find HDGF chunk definition on the classpath - " + chunkTableName);
	        }

	        try (BufferedReader inp = new BufferedReader(new InputStreamReader(cpd, LocaleUtil.CHARSET_1252))) {
				String line;
				while ((line = inp.readLine()) != null) {
					if (line.isEmpty() || "# \t".contains(line.substring(0, 1))) {
						continue;
					}

					// Start xxx
					if (!line.matches("^start [0-9]+$")) {
						throw new IllegalStateException("Expecting start xxx, found " + line);
					}
					int chunkType = Integer.parseInt(line.substring(6));
					ArrayList<CommandDefinition> defsL = new ArrayList<>();

					// Data entries
					while ((line = inp.readLine()) != null) {
						if (line.startsWith("end")) {
							break;
						}
						StringTokenizer st = new StringTokenizer(line, " ");
						int defType = Integer.parseInt(st.nextToken());
						int offset = Integer.parseInt(st.nextToken());
						String name = st.nextToken("\uffff").substring(1);

						CommandDefinition def = new CommandDefinition(defType, offset, name);
						defsL.add(def);
					}

					CommandDefinition[] defs = defsL.toArray(new CommandDefinition[0]);

					// Add to the map
					chunkCommandDefinitions.put(chunkType, defs);
				}
			}
		}
	}

	public int getVersion() { return version; }

	/**
	 * Creates the appropriate chunk at the given location.
	 *
	 * @param data the chunk bytes
	 * @param offset the offset into the chunk bytes array to start reading from
	 *
	 * @return the new Chunk
	 */
	public Chunk createChunk(byte[] data, int offset) {
		// Create the header
		ChunkHeader header =
			ChunkHeader.createChunkHeader(version, data, offset);
		// Sanity check
		if(header.getLength() < 0) {
			throw new IllegalArgumentException("Found a chunk with a negative length, which isn't allowed");
		}

		// How far up to look
		int endOfDataPos = offset + header.getLength() + header.getSizeInBytes();

		// Check we have enough data, and tweak the header size
		//  as required
		if(endOfDataPos > data.length) {
			LOG.atWarn().log("Header called for {} bytes, but that would take us past the end of the data!", box(header.getLength()));

			endOfDataPos = data.length;
			header.setLength(data.length - offset - header.getSizeInBytes());

			if(header.hasTrailer()) {
				header.setLength(header.getLength() - 8);
				endOfDataPos  -= 8;
			}
			if(header.hasSeparator()) {
                header.setLength(header.getLength() - 4);
				endOfDataPos  -= 4;
			}
		}


		// Create the trailer and separator, if required
		ChunkTrailer trailer = null;
		ChunkSeparator separator = null;
		if(header.hasTrailer()) {
			if(endOfDataPos <= data.length-8) {
				trailer = new ChunkTrailer(
					data, endOfDataPos);
				endOfDataPos += 8;
			} else {
				LOG.atError().log("Header claims a length to {} there's then no space for the trailer in the data ({})", box(endOfDataPos),box(data.length));
			}
		}
		if(header.hasSeparator()) {
			if(endOfDataPos <= data.length-4) {
				separator = new ChunkSeparator(
						data, endOfDataPos);
			} else {
				LOG.atError().log("Header claims a length to {} there's then no space for the separator in the data ({})", box(endOfDataPos),box(data.length));
			}
		}

		// Now, create the chunk
		byte[] contents = IOUtils.safelyClone(data, offset+header.getSizeInBytes(), header.getLength(), MAX_RECORD_LENGTH);
		Chunk chunk = new Chunk(header, trailer, separator, contents);

		// Feed in the stuff from  chunks_parse_cmds.tbl
		CommandDefinition[] defs = chunkCommandDefinitions.get(header.getType());
		if (defs == null) {
		    defs = new CommandDefinition[0];
		}
		chunk.setCommandDefinitions(defs);

		// Now get the chunk to process its commands
		chunk.processCommands();

		// All done
		return chunk;
	}

	/**
	 * The definition of a Command, which a chunk may hold.
	 * The Command holds the value, this describes it.
	 */
	public static class CommandDefinition {
		private int type;
		private int offset;
		private String name;
		public CommandDefinition(int type, int offset, String name) {
			this.type = type;
			this.offset = offset;
			this.name = name;
		}

		public String getName() {
			return name;
		}
		public int getOffset() {
			return offset;
		}
		public int getType() {
			return type;
		}
	}
}
