package ar.com.hjg.pngj.chunks;

import ar.com.hjg.pngj.ImageInfo;
import ar.com.hjg.pngj.PngReader;
import ar.com.hjg.pngj.PngWriter;

/**
 * Chunk copy policy to apply when copyng from a {@link PngReader} to a
 * {@link PngWriter}.
 * <p>
 * The constants are bit-masks, they can be OR-ed
 * <p>
 * Reference:
 * <a href="http://www.w3.org/TR/PNG/#14">http://www.w3.org/TR/PNG/#14</a> <br>
 */
public class ChunkCopyBehaviour {

	/** Don't copy anything */
	public static final int COPY_NONE = 0;

	/** copy the palette */
	public static final int COPY_PALETTE = 1;

	/** copy all 'safe to copy' chunks */
	public static final int COPY_ALL_SAFE = 1 << 2;

	/**
	 * copy all, including palette
	 */
	public static final int COPY_ALL = 1 << 3; // includes palette!
	/**
	 * Copy PHYS chunk (physical resolution)
	 */
	public static final int COPY_PHYS = 1 << 4; // dpi
	/**
	 * Copy al textual chunks.
	 */
	public static final int COPY_TEXTUAL = 1 << 5; // all textual types
	/**
	 * Copy TRNS chunk
	 */
	public static final int COPY_TRANSPARENCY = 1 << 6; //
	/**
	 * Copy unknown chunks (unknown by our factory)
	 */
	public static final int COPY_UNKNOWN = 1 << 7; // all unknown (by the factory!)
	/**
	 * Copy almost all: excepts only HIST (histogram) TIME and TEXTUAL chunks
	 */
	public static final int COPY_ALMOSTALL = 1 << 8;

	private static boolean maskMatch(final int v, final int mask) {
		return (v & mask) != 0;
	}

	/**
	 * Creates a predicate equivalent to the copy mask
	 * <p>
	 * Given a copy mask (see static fields) and the ImageInfo of the target
	 * PNG, returns a predicate that tells if a
	 * chunk should be copied.
	 * <p>
	 * This is a handy helper method, you can also create and set your own
	 * predicate
	 */
	public static ChunkPredicate createPredicate(final int copyFromMask, final ImageInfo imgInfo) {
		return chunk -> {
			if (chunk.crit) {
				if (chunk.id.equals(ChunkHelper.PLTE)) {
					if (imgInfo.indexed && ChunkCopyBehaviour.maskMatch(copyFromMask, ChunkCopyBehaviour.COPY_PALETTE))
						return true;
					if (!imgInfo.greyscale && ChunkCopyBehaviour.maskMatch(copyFromMask, ChunkCopyBehaviour.COPY_ALL))
						return true;
				}
			} else { // ancillary
				final boolean text = chunk instanceof PngChunkTextVar;
				final boolean safe = chunk.safe;
				// notice that these if are not exclusive
				if (ChunkCopyBehaviour.maskMatch(copyFromMask, ChunkCopyBehaviour.COPY_ALL))
					return true;
				if (safe && ChunkCopyBehaviour.maskMatch(copyFromMask, ChunkCopyBehaviour.COPY_ALL_SAFE))
					return true;
				if (chunk.id.equals(ChunkHelper.tRNS) && ChunkCopyBehaviour.maskMatch(copyFromMask, ChunkCopyBehaviour.COPY_TRANSPARENCY))
					return true;
				if (chunk.id.equals(ChunkHelper.pHYs) && ChunkCopyBehaviour.maskMatch(copyFromMask, ChunkCopyBehaviour.COPY_PHYS))
					return true;
				if (text && ChunkCopyBehaviour.maskMatch(copyFromMask, ChunkCopyBehaviour.COPY_TEXTUAL))
					return true;
				if (ChunkCopyBehaviour.maskMatch(copyFromMask, ChunkCopyBehaviour.COPY_ALMOSTALL) && !(ChunkHelper.isUnknown(chunk) || text || chunk.id.equals(ChunkHelper.hIST) || chunk.id.equals(ChunkHelper.tIME)))
					return true;
				if (ChunkCopyBehaviour.maskMatch(copyFromMask, ChunkCopyBehaviour.COPY_UNKNOWN) && ChunkHelper.isUnknown(chunk))
					return true;
			}
			return false;
		};
	}
}
