/*
 * Copyright (c) 2014-2021 by Wen Yu
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the Eclipse
 * Public License, v. 2.0 are satisfied: GNU General Public License, version 2
 * or any later version.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
 *
 * Change History - most recent changes go on top of previous changes
 *
 * Exif.java
 *
 * Who   Date       Description
 * ====  =======    =================================================
 * WY    10Apr2015  Moved data loaded checking to ExifReader
 * WY    31Mar2015  Fixed bug with getImageIFD() etc
 * WY    13Mar2015  Initial creation
 */

package pixy.meta.exif;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import android.graphics.Bitmap;
import pixy.meta.Metadata;
import pixy.meta.MetadataEntry;
import pixy.meta.MetadataType;
import pixy.meta.Thumbnail;
import pixy.meta.tiff.TIFFMeta;
import pixy.string.StringUtils;
import pixy.image.tiff.FieldType;
import pixy.image.tiff.IFD;
import pixy.image.tiff.Tag;
import pixy.image.tiff.TiffField;
import pixy.image.tiff.TiffTag;
import pixy.io.FileCacheRandomAccessInputStream;
import pixy.io.FileCacheRandomAccessOutputStream;
import pixy.io.IOUtils;
import pixy.io.RandomAccessInputStream;
import pixy.io.RandomAccessOutputStream;

/**
 * EXIF wrapper
 *  
 * @author Wen Yu, yuwen_66@yahoo.com
 * @version 1.0 03/13/2014
 */
public abstract class Exif extends Metadata {
	protected IFD imageIFD;
	protected IFD exifSubIFD;
	protected IFD gpsSubIFD;
	protected IFD interopSubIFD;
	protected ExifThumbnail thumbnail;
	protected short preferredEndian = IOUtils.BIG_ENDIAN;
	
	private boolean containsThumbnail;
	private boolean isThumbnailRequired;
	
	public static final int FIRST_IFD_OFFSET = 0x08;
	
	// Obtain a logger instance
	private static final Logger LOGGER = LoggerFactory.getLogger(Exif.class);
	
	public Exif() {
		super(MetadataType.EXIF);
		isDataRead = true;
	}
	
	public Exif(byte[] data) {
		super(MetadataType.EXIF, data);
		ensureDataRead();
	}
	
	public Exif(IFD imageIFD) {
		this();
		setImageIFD(imageIFD);
	}
	
	public Exif(InputStream is) throws IOException {
		this(IOUtils.inputStreamToByteArray(is));
	}
	
	public void addExifField(ExifTag tag, FieldType type, Object data) {
		if(exifSubIFD == null)
			exifSubIFD = new IFD();
		TiffField<?> field = FieldType.createField(tag, type, data);
		if(field != null)
			exifSubIFD.addField(field);
		else
			throw new IllegalArgumentException("Cannot create required EXIF TIFF field");
	}
	
	public void addGPSField(GPSTag tag, FieldType type, Object data) {
		if(gpsSubIFD == null)
			gpsSubIFD = new IFD();
		TiffField<?> field = FieldType.createField(tag, type, data);
		if(field != null)
			gpsSubIFD.addField(field);
		else
			throw new IllegalArgumentException("Cannot create required GPS TIFF field");
	}
	
	public void addInteropField(InteropTag tag, FieldType type, Object data) {
		if(interopSubIFD == null)
			interopSubIFD = new IFD();
		TiffField<?> field = FieldType.createField(tag, type, data);
		if(field != null)
			interopSubIFD.addField(field);
		else
			throw new IllegalArgumentException("Cannot create required interop TIFF field");
	}
	
	public void addImageField(TiffTag tag, FieldType type, Object data) {
		if(imageIFD == null)
			imageIFD = new IFD();
		TiffField<?> field = FieldType.createField(tag, type, data);
		if(field != null)
			imageIFD.addField(field);
		else
			throw new IllegalArgumentException("Cannot create required Image TIFF field");
	}
	
	public boolean containsThumbnail() {
		if(containsThumbnail)
			return true;
		if(thumbnail != null)
			return true;
		return false;
	}
	
	public IFD getExifIFD() {
		if(exifSubIFD != null) {
			return new IFD(exifSubIFD);
		}
		
		return null;
	}
	
	public IFD getGPSIFD() {
		if(gpsSubIFD != null) {
			return new IFD(gpsSubIFD);
		} 

		return null;
	}
	
	public IFD getInteropIFD() {
		if(interopSubIFD != null) {
			return new IFD(interopSubIFD);
		} 

		return null;
	}
	
	public IFD getImageIFD() {
		if(imageIFD != null) {
			return new IFD(imageIFD);
		}
		
		return null;		
	}
	
	private void getMetadataEntries(IFD currIFD, Class<? extends Tag> tagClass, List<MetadataEntry> items) {
		// Use reflection to invoke fromShort(short) method
		Method method = null;
		try {
			method = tagClass.getDeclaredMethod("fromShort", short.class);
		} catch (NoSuchMethodException e) {
			throw new RuntimeException("Method 'fromShort' is not defined for class " + tagClass);
		} catch (SecurityException e) {
			throw new RuntimeException("The operation is not allowed by the current security setup");
		}
		
		Collection<TiffField<?>> fields = currIFD.getFields();
		MetadataEntry entry = null;
		
		if(tagClass.equals(TiffTag.class)) {
			entry = new MetadataEntry("IFD0", "Image Info", true);
		} else if(tagClass.equals(ExifTag.class)) {
			entry = new MetadataEntry("EXIF SubIFD", "EXIF Info", true);
		} else if(tagClass.equals(GPSTag.class)) {
			entry = new MetadataEntry("GPS SubIFD", "GPS Info", true);
		} else if(tagClass.equals(InteropTag.class)) {
			entry = new MetadataEntry("Interoperability SubIFD", "Interoperability Info", true);
		} else
			entry = new MetadataEntry("UNKNOWN", "UNKNOWN SubIFD", true);
		
		for(TiffField<?> field : fields) {
			short tag = field.getTag();
			Tag ftag = TiffTag.UNKNOWN;
			if(tag == ExifTag.PADDING.getValue()) {
				ftag = ExifTag.PADDING;
			} else if(tag == ExifTag.EXIF_INTEROPERABILITY_OFFSET.getValue()) {
				ftag = ExifTag.EXIF_INTEROPERABILITY_OFFSET;
			} else {
				try {
					ftag = (Tag)method.invoke(null, tag);
				} catch (IllegalAccessException e) {
					throw new RuntimeException("Illegal access for method: " + method);
				} catch (IllegalArgumentException e) {
					throw new RuntimeException("Illegal argument for method:  " + method);
				} catch (InvocationTargetException e) {
					throw new RuntimeException("Incorrect invocation target");
				}
			}	
			if (ftag == TiffTag.UNKNOWN)
				LOGGER.warn("Tag: {} [Value: 0x{}] (Unknown)", ftag, Integer.toHexString(tag&0xffff));
			
			FieldType ftype = field.getType();				
						
			String tagString = null;
			if(ftype == FieldType.SHORT || ftype == FieldType.SSHORT)
				tagString = ftag.getFieldAsString(field.getDataAsLong());
			else
				tagString = ftag.getFieldAsString(field.getData());
			if(StringUtils.isNullOrEmpty(tagString))
				entry.addEntry(new MetadataEntry(ftag.getName(), field.getDataAsString()));
			else
				entry.addEntry(new MetadataEntry(ftag.getName(), tagString));
		}
		
		items.add(entry); // Add the Entry (group) into the collection
		
		Map<Tag, IFD> children = currIFD.getChildren();
		
		if(children.get(TiffTag.EXIF_SUB_IFD) != null) {
			getMetadataEntries(children.get(TiffTag.EXIF_SUB_IFD), ExifTag.class, items);
		}
		
		if(children.get(ExifTag.EXIF_INTEROPERABILITY_OFFSET) != null) {
			getMetadataEntries(children.get(ExifTag.EXIF_INTEROPERABILITY_OFFSET), InteropTag.class, items);
		}
		
		if(children.get(TiffTag.GPS_SUB_IFD) != null) {
			getMetadataEntries(children.get(TiffTag.GPS_SUB_IFD), GPSTag.class, items);
		}		
	}

	public ExifThumbnail getThumbnail() {
		if(thumbnail != null)
			return new ExifThumbnail(thumbnail);
	
		return null;
	}
	
	public boolean isThumbnailRequired() {
		return isThumbnailRequired;
	}
	
	public short getPreferredEndian() {
		return preferredEndian;
	}
	
	public Iterator<MetadataEntry> iterator() {
		ensureDataRead();
		List<MetadataEntry> items = new ArrayList<MetadataEntry>();
		if(imageIFD != null)
			getMetadataEntries(imageIFD, TiffTag.class, items);
		if(containsThumbnail) {
			MetadataEntry thumbnailEntry = new MetadataEntry("IFD1", "Thumbnail Image", true);
			thumbnailEntry.addEntry(new MetadataEntry("Thumbnail format", (thumbnail.getDataType() == 1? "DATA_TYPE_KJpegRGB":"DATA_TYPE_TIFF")));
			thumbnailEntry.addEntry(new MetadataEntry("Thumbnail data length", "" + thumbnail.getCompressedImage().length));
			items.add(thumbnailEntry);
		}
	
		return Collections.unmodifiableList(items).iterator();
	}
	
	public void read() throws IOException {
		if(!isDataRead) {
			RandomAccessInputStream exifIn = new FileCacheRandomAccessInputStream(new ByteArrayInputStream(data));
			List<IFD> ifds = new ArrayList<IFD>(3);
			TIFFMeta.readIFDs(ifds, exifIn);
			
			preferredEndian = exifIn.getEndian();
			
			if(ifds.size() > 0) {
				imageIFD = ifds.get(0);
				exifSubIFD = imageIFD.getChild(TiffTag.EXIF_SUB_IFD);
				if(exifSubIFD != null)
					interopSubIFD = exifSubIFD.getChild(ExifTag.EXIF_INTEROPERABILITY_OFFSET);
				gpsSubIFD = imageIFD.getChild(TiffTag.GPS_SUB_IFD);
			}
		    // We have thumbnail IFD
		    if(ifds.size() >= 2) {
		    	IFD thumbnailIFD = ifds.get(1);
		    	int width = -1;
		    	int height = -1;
		    	TiffField<?> field = thumbnailIFD.getField(TiffTag.IMAGE_WIDTH);
		    	if(field != null) 
		    		width = field.getDataAsLong()[0];
		    	field = thumbnailIFD.getField(TiffTag.IMAGE_LENGTH);
		    	if(field != null)
		    		height = field.getDataAsLong()[0];
		    	field = thumbnailIFD.getField(TiffTag.JPEG_INTERCHANGE_FORMAT);
		    	if(field != null) { // JPEG format, save as JPEG
		    		int thumbnailOffset = field.getDataAsLong()[0];
		    		field = thumbnailIFD.getField(TiffTag.JPEG_INTERCHANGE_FORMAT_LENGTH);
		    		int thumbnailLen = field.getDataAsLong()[0];
		    		exifIn.seek(thumbnailOffset);
		    		byte[] thumbnailData = new byte[thumbnailLen];
		    		exifIn.readFully(thumbnailData);
		    		thumbnail = new ExifThumbnail(width, height, Thumbnail.DATA_TYPE_KJpegRGB, thumbnailData, thumbnailIFD);
		    		containsThumbnail = true;				    
		    	} else { // Uncompressed TIFF
		    		field = thumbnailIFD.getField(TiffTag.STRIP_OFFSETS);
		    		if(field == null) 
		    			field = thumbnailIFD.getField(TiffTag.TILE_OFFSETS);
		    		if(field != null) {
		    			 exifIn.seek(0);
		    			 ByteArrayOutputStream bout = new ByteArrayOutputStream();
		    			 RandomAccessOutputStream tiffout = new FileCacheRandomAccessOutputStream(bout);
		    			 TIFFMeta.retainPages(exifIn, tiffout, 1);
		    			 tiffout.close(); // Auto flush when closed
		    			 thumbnail = new ExifThumbnail(width, height, Thumbnail.DATA_TYPE_TIFF, bout.toByteArray(), thumbnailIFD);
		    			 containsThumbnail = true;		    			    
		    		}
		    	}
		    }
		    exifIn.close();		
		    isDataRead = true;
		}
	}
	
	public void setExifIFD(IFD exifSubIFD) {
		this.exifSubIFD = exifSubIFD;
	}
	
	public void setGPSIFD(IFD gpsSubIFD) {
		this.gpsSubIFD = gpsSubIFD;
	}
	
	public void setInteropIFD(IFD interopSubIFD) {
		this.interopSubIFD = interopSubIFD;
	}
	
	public void setImageIFD(IFD imageIFD) {
		if(imageIFD == null)
			throw new IllegalArgumentException("Input image IFD is null");
		this.imageIFD = imageIFD;
		this.exifSubIFD = imageIFD.getChild(TiffTag.EXIF_SUB_IFD);
		this.gpsSubIFD = imageIFD.getChild(TiffTag.GPS_SUB_IFD);
	}
	
	/**
	 * @param thumbnail a Thumbnail instance. If null, a thumbnail
	 *        will be generated from the input image.
	 */	
	public void setThumbnail(ExifThumbnail thumbnail) {
		this.thumbnail = thumbnail;
	}
	
	public void setThumbnailImage(Bitmap thumbnail) {
		if(this.thumbnail == null)
			this.thumbnail = new ExifThumbnail(); 
		this.thumbnail.setImage(thumbnail);
	}
	
	public void setThumbnailRequired(boolean isThumbnailRequired) {
		this.isThumbnailRequired = isThumbnailRequired;
	}
	
	public void setPreferredEndian(short preferredEndian) {
		if(preferredEndian != IOUtils.BIG_ENDIAN && preferredEndian != IOUtils.LITTLE_ENDIAN)
			throw new IllegalArgumentException("Invalid Exif endian!");
		this.preferredEndian = preferredEndian;
	}
		
	public abstract void write(OutputStream os) throws IOException;
}
