/********************************************************************************
 * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 ********************************************************************************/


package org.eclipse.mdm.mdfsorter.mdf3;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.LinkedList;
import java.util.logging.Level;

import org.eclipse.mdm.mdfsorter.MDFAbstractParser;
import org.eclipse.mdm.mdfsorter.MDFFileContent;
import org.eclipse.mdm.mdfsorter.MDFParser;
import org.eclipse.mdm.mdfsorter.MDFSorter;
import org.eclipse.mdm.mdfsorter.mdf4.MDF4Util;

public class MDF3Parser extends MDFAbstractParser<MDF3GenBlock> {

	public MDF3Parser(FileChannel in, boolean isBigEndian) {
		super(in);
		this.isBigEndian = isBigEndian;
	}

	public boolean isBigEndian = false;

	/**
	 * Helper Method to read to an array from a FileChannel.
	 *
	 * @param bytes
	 *            The number of bytes to read.
	 * @param in
	 *            The FileChannel to read from.
	 * @return A byte-Array with <code>length=bytes</code> filled with the next
	 *         bytes from the Channel.
	 * @throws IOException
	 *             If an input error occurs.
	 */
	private static byte[] readBytes(int bytes, FileChannel in) throws IOException {
		ByteBuffer chunk = ByteBuffer.allocate(bytes);
		int bytesread = 0;
		if ((bytesread = in.read(chunk)) != bytes) {
			System.err.println("Read only " + bytesread + " Bytes instead of " + bytes);
		}
		return chunk.array();
	}

	/**
	 * Parses the file and returns the root of the tree structure.
	 *
	 * @return The HeaderBlock that is root of the file
	 * @throws IOException
	 */
	private MDF3GenBlock parseBlocks() throws IOException {
		// Add headerblock to the queue
		MDF3GenBlock g = new MDF3GenBlock(64, isBigEndian);
		queue.add(g);
		MDF3GenBlock ret = g;
		do {
			skipped.clear();
			while (!queue.isEmpty()) {
				MDF3GenBlock next = queue.poll();

				if (blocklist.containsKey(next.getPos())) {
					throw new RuntimeException("Duplicate Block in list.");
				}

				if (next.getPos() < lasthandled) {
					skipped.add(next);
					continue;
				}

				// parse.
				getBlockHeader(next);
				forceparse(next);

				// Add (if possible the more precise) block to the blocklist
				unfinished.remove(next.getPos());
				if (next.getPrec() != null) {
					blocklist.put(next.getPos(), next.getPrec());
				} else {
					blocklist.put(next.getPos(), next);
				}

				lasthandled = next.getPos();

				foundblocks++;
			}
			in.position(0L);
			queue.addAll(skipped);
			lasthandled = 0;
			fileruns++;
		} while (!skipped.isEmpty()); // another run is needed

		MDFSorter.log.log(Level.INFO, "Needed " + fileruns + " runs.");
		MDFSorter.log.log(Level.INFO, "Found " + blocklist.size() + " blocks.");
		MDFSorter.log.log(Level.FINE, "ValidatorListSize: " + (foundblocks + 1)); // Expected
																					// number
		// of node in Vector
		// MDFValidators
		// node list for
		// this file
		return ret;
	}

	/**
	 * Reads the Block Header of an MDFGenBlock, where only the position value
	 * is set. The header includes ID, linkcount and length and also the links
	 * of the link section!
	 *
	 * @throws IOException
	 *             If a reading error occurs.
	 */
	private void getBlockHeader(MDF3GenBlock start) throws IOException {
		in.position(start.getPos());
		byte[] head = readBytes(4, in);
		// Read header of this block
		String blktyp = MDF3Util.readCharsISO8859(MDFParser.getDataBuffer(head, 0, 2), 2);
		start.setId(blktyp);
		int blklength = MDF4Util.readUInt16(MDFParser.getDataBuffer(head, 2, 4));
		start.setLength(blklength);

		// set standard link-count
		int blklinkcount = MDF3Util.getLinkcount(blktyp);
		start.setLinkCount(blklinkcount);

		// Read links and create new blocks
		head = readBytes(blklinkcount * 4, in);
		long position = in.position();
		for (int i = 0; i < blklinkcount; i++) {
			long nextlink = MDF3Util.readLink(MDFParser.getDataBuffer(head, i * 4, (i + 1) * 4), isBigEndian);
			if (nextlink != 0) {
				if (blktyp.equals("DG") && i == 3) {
					// special case: pointer to data section (4th link of a DG-BLock)

					/*
					 * the following lines ensure validity of a given link to a DTBLOCK,
					 * since there are cases where a LINK is given but points to a non
					 * DTBLOCK. therefore such links are only proceeded if the corresponding
					 * DGBLOCK has at least one CGBLOCK with at least one measured value!
					 */
					DGBLOCK dgBlock = new DGBLOCK(start);
					in.position(dgBlock.getPos() + 20);
					byte[] bb = readBytes(2, in);
					int cgCount = MDF3Util.readUInt16(MDFParser.getDataBuffer(bb, 0, 2), isBigEndian);
					if (cgCount < 1) {
						// ignore link, since DGBLOCK does not have any CGBLOCKs
						continue;
					}

					// iterate over all CGBLOCKS. link is valid if at least one of them has measured values
					CGBLOCK cgBlock = new CGBLOCK(dgBlock.getLnkCgFirst());
					while (cgBlock != null) {
						in.position(cgBlock.getPos() + 22);
						bb = readBytes(4, in);
						long cycleCount = MDF3Util.readUInt32(MDFParser.getDataBuffer(bb, 0, 4), isBigEndian);
						if (cycleCount > 0) {
							checkFoundDataBlockLink(start, nextlink, i);
							break;
						}
						cgBlock = --cgCount == 0 ? null : new CGBLOCK(cgBlock.getLnkCgNext());
					}
				} else {
					checkFoundLink(start, nextlink, i);
				}
			}
		}

		// set to begin of data section.
		in.position(position);

		// read possible extra links in CGBLOCK
		if (blktyp.equals("CG") && blklength == 30) {
			head = readBytes(14, in);
			long nextlink = MDF3Util.readLink(MDFParser.getDataBuffer(head, 10, 14), isBigEndian);
			start.moreLinks(4);
			checkFoundLink(start, nextlink, 3);
		}

		// read possible extra links CNBLOCK
		if (blktyp.equals("CN") && blklength > 218) {
			head = readBytes(198, in);
			long nextlink = MDF3Util.readLink(MDFParser.getDataBuffer(head, 194, 198), isBigEndian);
			start.moreLinks(6);
			if (nextlink != 0) {
				checkFoundLink(start, nextlink, 5);
			}

			if (blklength > 222) {
				head = readBytes(4, in);
				nextlink = MDF3Util.readLink(MDFParser.getDataBuffer(head, 0, 4), isBigEndian);
				start.moreLinks(7);
				if (nextlink != 0) {
					checkFoundLink(start, nextlink, 6);
				}
			}
		}

		// read possible extra links CCBLOCK
		if (blktyp.equals("CC")) {
			head = readBytes(40, in);
			int convtype = MDF3Util.readUInt16(MDFParser.getDataBuffer(head, 38, 40), isBigEndian);
			if (convtype == 12) {
				// TextTable has links to textblocks, get number
				head = readBytes(2, in);
				int numberOfValues = MDF3Util.readUInt16(MDFParser.getDataBuffer(head, 0, 2), isBigEndian);
				start.moreLinks(numberOfValues);
				head = readBytes((8 + 8 + 4) * numberOfValues, in);
				for (int i = 0; i < numberOfValues; i++) {
					long nextlink = MDF3Util.readLink(MDFParser.getDataBuffer(head, i * 20 + 16, (i + 1) * 20),
							isBigEndian);
					if (nextlink != 0) {
						checkFoundLink(start, nextlink, i);
					}
				}
			}
		}

		// read possible extra links CDBLOCK
		if (blktyp.equals("CD")) {
			head = readBytes(4, in);
			int numdep = MDF3Util.readUInt16(MDFParser.getDataBuffer(head, 2, 4), isBigEndian);
			start.moreLinks(2 * numdep);
			head = readBytes(8 * numdep, in);
			for (int i = 0; i < 2 * numdep; i++) {
				long nextlink = MDF3Util.readLink(MDFParser.getDataBuffer(head, 4 * i, 4 * (i + 1)), isBigEndian);
				if (nextlink != 0) {
					checkFoundLink(start, nextlink, i);
				}
			}
		}

		// set stream back to start of data section.
		in.position(position);
	}

	/**
	 * Checks if a newly found link, already exists in some other list. If not,
	 * it is added to the blocklist.
	 *
	 * @param start
	 *            The block, as which child this link was recovered.
	 * @param address
	 *            The offset in the file of this link.
	 * @param chldnum
	 *            The number of this link.
	 */
	public void checkFoundLink(MDF3GenBlock start, long address, int chldnum) {
		if (blocklist.containsKey(address)) {
			start.addLink(chldnum, blocklist.get(address));
			foundblocks++;
		} else if (unfinished.containsKey(address)) {
			start.addLink(chldnum, unfinished.get(address));
			foundblocks++;
		} else {
			MDF3GenBlock child = new MDF3GenBlock(address, isBigEndian);
			start.addLink(chldnum, child);
			queue.add(child);
			unfinished.put(address, child);
		}
	}

	/**
	 * If a newly found block links to a data section, it is immediately put
	 * into the blocklist.
	 *
	 * @param start
	 *            The parent block of the found data section
	 * @param address
	 *            The address of the found data block.
	 * @param chldnum
	 *            The number of the link from startblock to the found
	 *            childblock.
	 */
	public void checkFoundDataBlockLink(MDF3GenBlock start, long address, int chldnum) {
		foundblocks++;
		if (blocklist.containsKey(address)) {
			start.addLink(chldnum, blocklist.get(address));
		} else {
			MDF3GenBlock child = new MDF3GenBlock(address, isBigEndian);
			child.setId("DT"); // TODO Other types;
			child.setLinkCount(0);
			child = new DTBLOCK(child);
			blocklist.put(address, child);
			start.addLink(chldnum, child);
		}
	}

	/**
	 * This method creates the corresponding specialized block and calls the
	 * parse method on Block blk
	 *
	 * @param blk
	 * @throws IOException
	 */
	/**
	 * @param blk
	 * @throws IOException
	 */
	private void forceparse(MDF3GenBlock blk) throws IOException {

		long sectionsize = blk.getLength() - 4 - 4 * MDF3Util.getLinkcount(blk.getId());

		byte[] content = null;

		// parse special blocktypes more precisely.
		content = readBytes((int) sectionsize, in);

		MDF3GenBlock sp = null;

		switch (blk.getId()) {
		case "CG":
			sp = new CGBLOCK(blk);
			break;
		case "DG":
			sp = new DGBLOCK(blk);
			break;
		case "CN":
			sp = new CNBLOCK(blk);
			break;
		case "HD":
			sp = new HDBLOCK(blk);
			break;
		case "CC":
			sp = new CCBLOCK(blk);
			break;
		case "CD":
			sp = new CDBLOCK(blk);
			break;
		}

		if (sp != null) {
			sp.parse(content);
		}
	}

	private LinkedList<MDF3GenBlock> getBlocklist() {
		LinkedList<MDF3GenBlock> writelist = new LinkedList<>();
		while (!blocklist.isEmpty()) {
			writelist.addFirst(blocklist.pollLastEntry().getValue());

		}
		return writelist;
	}

	@Override
	public MDFFileContent<MDF3GenBlock> parse() throws IOException {

		MDF3GenBlock tree = parseBlocks();

		// 2. run through tree, and change all blocks to their specials if they
		// exist

		LinkedList<MDF3GenBlock> structlist = getBlocklist();
		if (tree.getPrec() != null) {
			tree = tree.getPrec();
		}
		// update children and calculate length of data blocks
		for (MDF3GenBlock blk : structlist) {
			blk.updateChildren();
		}

		// calculate length of data sections.
		for (MDF3GenBlock blk : structlist) {
			if (blk instanceof DGBLOCK) {
				DGBLOCK dgthis = (DGBLOCK) blk;
				MDF3GenBlock datasec = dgthis.getLnkData();
				if (datasec != null) {
					long datalength = 0;
					MDF3GenBlock cgfirst = dgthis.getLnkCgFirst();
					if (!(cgfirst instanceof CGBLOCK)) {
						throw new RuntimeException("Error reading CGBLOCK");
					}
					CGBLOCK childcg = (CGBLOCK) dgthis.getLnkCgFirst();
					do {
						datalength += (childcg.getDataBytes() + dgthis.getNumOfRecId()) * childcg.getCycleCount();
					} while ((childcg = (CGBLOCK) childcg.getLnkCgNext()) != null);

					datasec.setLength(datalength);
				}
			}
		}
		tree.updateChildren();

		return new MDFFileContent<MDF3GenBlock>(in, tree, structlist, true);
	}

}
