/********************************************************************************
 * 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.openatfx.mdf.mdf4;

import static java.lang.Math.min;
import static java.nio.file.StandardOpenOption.CREATE_NEW;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;

import org.asam.ods.T_ExternalReference;

/**
 * <p>
 * THE ATTACHMENT BLOCK <code>ATBLOCK</code>
 * </p>
 * The data section of the ATBLOCK contains attachments (binary data)
 *
 * @author Christian Rechner, Tobias Leemann
 */
class ATBLOCK extends BLOCK {

	public static String BLOCK_ID = "##AT";

	private long lnkAtNext;

	private long lnkTxFilename;

	private long lnkTxMIMEtype;

	private long lnkMdComment;

	private int flags;

	private int creatorIndex;

	private byte[] md5CheckSum;

	private long origSize;

	private long embeddedSize;

	/**
	 * Constructor.
	 *
	 * @param sbc
	 *            The byte channel pointing to the MDF file.
	 * @param pos
	 *            The position of the block within the MDF file.
	 */
	private ATBLOCK(SeekableByteChannel sbc, long pos) {
		super(sbc, pos);
	}

	public long getLnkAtNext() {
		return lnkAtNext;
	}

	public void setLnkAtNext(long lnkAtNext) {
		this.lnkAtNext = lnkAtNext;
	}

	public long getLnkTxFilename() {
		return lnkTxFilename;
	}

	public void setLnkTxFilename(long lnkTxFilename) {
		this.lnkTxFilename = lnkTxFilename;
	}

	public long getLnkTxMIMEtype() {
		return lnkTxMIMEtype;
	}

	public void setLnkTxMIMEtype(long lnkTxMIMEtype) {
		this.lnkTxMIMEtype = lnkTxMIMEtype;
	}

	public long getLnkMdComment() {
		return lnkMdComment;
	}

	public void setLnkMdComment(long lnkMdComment) {
		this.lnkMdComment = lnkMdComment;
	}

	public int getFlags() {
		return flags;
	}

	public void setFlags(int flags) {
		this.flags = flags;
	}

	public int getCreatorIndex() {
		return creatorIndex;
	}

	public void setCreatorIndex(int creatorIndex) {
		this.creatorIndex = creatorIndex;
	}

	public byte[] getMd5CheckSum() {
		return md5CheckSum;
	}

	public void setMd5CheckSum(byte[] md5CheckSum) {
		this.md5CheckSum = md5CheckSum;
	}

	public long getOrigSize() {
		return origSize;
	}

	public void setOrigSize(long origSize) {
		this.origSize = origSize;
	}

	public long getEmbeddedSize() {
		return embeddedSize;
	}

	public void setEmbeddedSize(long embeddedSize) {
		this.embeddedSize = embeddedSize;
	}

	public ATBLOCK getAtNextBlock() throws IOException {
		if (lnkAtNext > 0) {
			return ATBLOCK.read(sbc, lnkAtNext);
		}
		return null;
	}

	public TXBLOCK getTxFilennameBlock() throws IOException {
		if (lnkTxFilename > 0) {
			return TXBLOCK.read(sbc, lnkTxFilename);
		}
		return null;
	}

	public TXBLOCK getTxMIMETypeBlock() throws IOException {
		if (lnkTxMIMEtype > 0) {
			return TXBLOCK.read(sbc, lnkTxMIMEtype);
		}
		return null;
	}

	public TXBLOCK getTxCommentBlock() throws IOException {
		if (lnkMdComment > 0) {
			return TXBLOCK.read(sbc, lnkMdComment);
		}
		return null;
	}

	public MDBLOCK getMdCommentBlock() throws IOException {
		if (lnkMdComment > 0) {
			return MDBLOCK.read(sbc, lnkMdComment);
		}
		return null;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String toString() {
		return "DTBLOCK [pos=" + getPos() + "]";
	}

	/**
	 * Reads a SDBLOCK from the channel starting at current channel position.
	 *
	 * @param channel
	 *            The channel to read from.
	 * @param pos
	 *            The position
	 * @return The block data.
	 * @throws IOException
	 *             The exception.
	 */
	public static ATBLOCK read(SeekableByteChannel channel, long pos) throws IOException {
		ATBLOCK block = new ATBLOCK(channel, pos);

		// read block header
		ByteBuffer bb = ByteBuffer.allocate(24 + 32 + 40); // 24 Head 32 Links
															// 40 Data
		bb.order(ByteOrder.LITTLE_ENDIAN);
		channel.position(pos);
		channel.read(bb);
		bb.rewind();

		// CHAR 4: Block type identifier
		block.setId(MDF4Util.readCharsISO8859(bb, 4));
		if (!block.getId().equals(BLOCK_ID)) {
			throw new IOException("Wrong block type - expected '" + BLOCK_ID + "', found '" + block.getId() + "'");
		}

		// BYTE 4: Reserved used for 8-Byte alignment
		bb.get(new byte[4]);

		// UINT64: Length of block
		block.setLength(MDF4Util.readUInt64(bb));

		// UINT64: Number of links
		block.setLinkCount(MDF4Util.readUInt64(bb));

		// LINK 1 Pointer to next ATBLOCK (NIL allowed)
		block.setLnkAtNext(MDF4Util.readLink(bb));

		// LINK 1 Pointer to Text Block with Filename (NIL allowed)
		block.setLnkTxFilename(MDF4Util.readLink(bb));

		// LINK 1 Pointer to Text Block with MIME Type (TXBLOCK) (NIL allowed)
		block.setLnkTxMIMEtype(MDF4Util.readLink(bb));

		// LINK 1 Pointer to comment Block MDBLOCK (NIL allowed)
		block.setLnkMdComment(MDF4Util.readLink(bb));

		// UINT16 flags
		block.setFlags(MDF4Util.readUInt16(bb));

		// UINT16 Creator Index
		block.setCreatorIndex(MDF4Util.readUInt16(bb));

		// BYTE 4: Reserved used for 8-Byte alignment
		bb.get(new byte[4]);

		// BYTE 16: MD5 Checksum
		byte[] md5sum = new byte[16];
		bb.get(md5sum);
		block.setMd5CheckSum(md5sum);

		// UINT64 OriginalSize
		block.setOrigSize(MDF4Util.readUInt64(bb));

		// UINT64 EmbeddedSize
		block.setEmbeddedSize(MDF4Util.readUInt64(bb));

		return block;
	}

	/**
	 * Converts this AT Block and all linked one into dedicated
	 * external links, where each embedded file is written to disc.
	 *
	 * @param target  the working directory
	 * @param subDir  name of the target sub directory for exporting embedded files, may be empty
	 * @return  all external links, neither null nor empty
	 * @throws IOException  in case of errors
	 */
	public T_ExternalReference[] toExtRefs(Path target, String subDir) throws IOException {
		List<T_ExternalReference> extRefs = new ArrayList<>();
		ATBLOCK block = this;

		int count = 0;
		while (block != null) {
			boolean embedded = (block.flags & 1) != 0;

			Path file;
			if (embedded) {
				file = block.exportEmbedded(subDir.isEmpty() ? target : target.resolve(subDir), ++count);
			} else {
				file = block.getFilePath(target, true);
			}

			block.checkMD5(file);

			extRefs.add(new T_ExternalReference(block.getDescription(), block.getMimeType(file),
					target.relativize(file).toString()));
			block = block.getAtNextBlock();
		}

		return extRefs.stream().toArray(T_ExternalReference[]::new);
	}

	/**
	 * Returns the file MIME type if available.
	 *
	 * @return  the MIME type, may be empty but not null
	 * @throws IOException  in case of errors
	 */
	private String getMimeType(Path file) throws IOException {
		String value = Files.probeContentType(file);
		if (lnkTxMIMEtype > 0) {
			value = getTxMIMETypeBlock().getTxData();
		}

		return value == null ? "application/octet-stream" : value.trim();
	}

	/**
	 * Returns the file description if available.
	 *
	 * @return  the file description, may be empty but not null
	 * @throws IOException  in case of errors
	 */
	private String getDescription() throws IOException {
		if (lnkMdComment < 1) {
			return "";
		}

		String value = null;
		try {
			value = getMdCommentBlock().getMdData();
		} catch (IOException e) {
			value = getTxCommentBlock().getTxData();
		}

		return value == null ? "" : value.trim();
	}

	/**
	 * Exports given embedded stream into given file.
	 *
	 * @param target  the target file path, not null and must not exist yet
	 * @param id  the internal files count, used to index files whose name is unknown
	 * @return  the newly created file path, not null
	 * @throws IOException  in case of errors
	 */
	private Path exportEmbedded(Path target, int id) throws IOException {
		if ((flags & 1) == 0) {
			throw new IllegalStateException("file is not embedded");
		}

		Path file;
		if (lnkTxFilename > 0) {
			file = getFilePath(target, false);
		} else {
			file = target.resolve("embedded_" + id + ".bin");
		}

		Files.createDirectories(file.getParent());
		EmbeddedStream embeddedStream = new EmbeddedStream(sbc, getPos() + 96, getEmbeddedSize());
		boolean compressed = (flags & 1 << 1) != 0;
		if (compressed) {
			unzip(embeddedStream, file);
		} else {
			Files.copy(embeddedStream, file);
		}

		return file;
	}

	/**
	 * Exports given compressed embedded inputs stream into given file target.
	 *
	 * @param embeddedStream  the embedded input stream, not null
	 * @param target  the target file path, not null and must not exist yet
	 * @throws IOException  in case of errors
	 */
	private void unzip(EmbeddedStream embeddedStream, Path target) throws IOException {
		try (InputStream is = embeddedStream; OutputStream os = Files.newOutputStream(target, CREATE_NEW)) {
			Inflater inflater =  new Inflater();

			byte[] writeBuffer = new byte[8192];
			byte[] readBuffer = new byte[8192];
			int written;
			int read = 0;
			while(read > -1 && !inflater.finished()) {
				while(inflater.needsInput() && (read = is.read(readBuffer)) > 0) {
					// feed iflater as long as it needs input and as long as there is data available
					inflater.setInput(readBuffer, 0, read);
				}

				while ((written = inflater.inflate(writeBuffer)) > 0) {
					// write decompressed bytes as long inflater is satisfied
					os.write(writeBuffer, 0, written);
				}
			}

			os.flush();
		} catch (DataFormatException e) {
			throw new IOException("failed to decompress embedded file", e);
		}
	}

	/**
	 * Returns the file path.
	 *
	 * @param target  the working directory
	 * @param exists  if true, the returned file path must exist
	 * @return  the target file path, not null
	 * @throws IOException  in case of errors
	 */
	private Path getFilePath(Path target, boolean exists) throws IOException {
		if (lnkTxFilename < 1) {
			throw new IllegalStateException("file name TXBLOCK is not set");
		}

		TXBLOCK fileNameTX = getTxFilennameBlock();
		Path file = Paths.get(fileNameTX.getTxData());
		if (!file.isAbsolute()) {
			file = target.resolve(fileNameTX.getTxData());
		}

		if (exists && !file.toFile().exists()) {
			throw new IOException("file '" + file + "' not found.");
		}

		return file;
	}

	/**
	 * Compares calculated MD5 checksum with the stored one.
	 *
	 * @param file  the file path, not null
	 * @throws IOException  in case of errors
	 */
	private void checkMD5(Path file) throws IOException {
		if ((flags & 1 << 2) == 0) {
			// checksum is not available => skip!
			return;
		}
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			try (DigestInputStream is = new DigestInputStream(Files.newInputStream(file), md)) {
				byte[] buffer = new byte[1024];
				while (is.read(buffer) != -1);
				byte[] calculated = is.getMessageDigest().digest();
				if (!Arrays.equals(calculated, getMd5CheckSum())) {
					throw new IOException("checksum validation failed for file '" + file + "'");
				}
			}
		} catch (NoSuchAlgorithmException e) {
			throw new IOException("checksum algorithm 'MD5' not found.");
		}
	}

	/**
	 * Embedded input stream implementation.
	 */
	private static final class EmbeddedStream extends InputStream {

		private final SeekableByteChannel sbc;
		private final long length0;

		private long current = 0;

		/**
		 * Constructor.
		 *
		 * @param sbc  the channel source for byte access, not null
		 * @param start  the channel position this stream internally starts from
		 * @param length  the number of bytes this stream will provide
		 * @throws IOException  in case of errors
		 */
		public EmbeddedStream(SeekableByteChannel sbc, long start, long length) throws IOException {
			this.sbc = sbc;
			this.length0 = length;

			sbc.position(start);
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public int read() throws IOException {
			if (current >= length0) {
				return -1;
			}

			ByteBuffer buffer = ByteBuffer.allocate(1);
			int read = sbc.read(buffer);
			if (read > 0) {
				current += read;
				buffer.rewind();
				return buffer.getInt();
			} else {
				return -1;
			}
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public int read(byte[] bytes) throws IOException {
			if (current >= length0) {
				return -1;
			}

			int read = (int) min(sbc.read(ByteBuffer.wrap(bytes)), length0 - current);
			if (read > 0) {
				current += read;
				return read;
			} else {
				return -1;
			}
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public int read(byte[] bytes, int offset, int length) throws IOException {
			if (current >= length0) {
				return -1;
			}

			int read = (int) min(sbc.read(ByteBuffer.wrap(bytes, offset, length)), length0 - current);
			if (read > 0) {
				current += read;
				return read;
			} else {
				return -1;
			}
		}

	}
}