package cn.reghao.tnb.file.app.util;

import cn.reghao.tnb.content.api.dto.CamPhoto;
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.lang.GeoLocation;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import com.drew.metadata.exif.ExifIFD0Directory;
import com.drew.metadata.exif.GpsDirectory;
import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.ImageWriteException;
import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;
import org.apache.commons.imaging.formats.jpeg.xmp.JpegXmpRewriter;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collection;

/**
 * @author reghao
 * @date 2023-09-06 14:25:18
 */
public class PhotoExif {
    public static void getExifInfo(File file) throws ImageProcessingException, IOException {
        Metadata metadata = ImageMetadataReader.readMetadata(file);

        for (Directory directory : metadata.getDirectories()) {
            for (Tag tag : directory.getTags()) {
                String dirname = tag.getDirectoryName();
                String name = tag.getTagName();
                String description = tag.getDescription();
                System.out.println(dirname + ":" + name + " -> " + description);
            }
        }

        Collection<GpsDirectory> gpsDirectories = metadata.getDirectoriesOfType(GpsDirectory.class);
        for(GpsDirectory gps : gpsDirectories) {
            GeoLocation geoLocation = gps.getGeoLocation();
            if (geoLocation != null) {
                double longitude = geoLocation.getLongitude();
                double latitude = geoLocation.getLatitude();
                System.out.printf("%s,%s\n", latitude, longitude);
            }
        }
    }

    public static String removeExif(File srcFile) throws IOException, ImageWriteException, ImageReadException {
        String parentPath = srcFile.getParent();
        String srcName = srcFile.getName();
        int idx = srcName.lastIndexOf(".");
        if (idx == -1) {
            throw new IOException("photo file not end with suffix");
        }

        String destName = String.format("%s_noexif%s", srcName.substring(0, idx), srcName.substring(idx));
        String destPath = String.format("%s%s%s", parentPath, File.separator, destName);
        FileOutputStream fos = new FileOutputStream(destPath);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ExifRewriter exifRewriter = new ExifRewriter();
        exifRewriter.removeExifMetadata(srcFile, baos);

        JpegXmpRewriter jpegXmpRewriter = new JpegXmpRewriter();
        jpegXmpRewriter.removeXmpXml(baos.toByteArray(), fos);
        return destPath;
    }

    public static CamPhoto getCamPhoto(String filePath) {
        File file = new File(filePath);
        if (!file.exists()) {
            return null;
        }

        CamPhoto camPhoto = new CamPhoto(filePath);
        try {
            Metadata metadata = ImageMetadataReader.readMetadata(file);
            Collection<GpsDirectory> gpsDirectories = metadata.getDirectoriesOfType(GpsDirectory.class);
            for(GpsDirectory gps : gpsDirectories) {
                GeoLocation geoLocation = gps.getGeoLocation();
                if (geoLocation != null) {
                    double longitude = geoLocation.getLongitude();
                    double latitude = geoLocation.getLatitude();

                    camPhoto.setLongitude(longitude);
                    camPhoto.setLatitude(latitude);
                }
            }

            Collection<ExifIFD0Directory> exifDirectories = metadata.getDirectoriesOfType(ExifIFD0Directory.class);
            for (ExifIFD0Directory exif : exifDirectories) {
                for (Tag tag : exif.getTags()) {
                    String tagName = tag.getTagName();
                    String desc = tag.getDescription();
                    switch (tagName) {
                        case "Make":
                            camPhoto.setManufacturer(desc);
                            break;
                        case "Model":
                            camPhoto.setModel(desc);
                            break;
                        case "Software":
                            camPhoto.setSoftware(desc);
                            break;
                        case "Date/Time":
                            String[] arr = desc.split(" ");
                            if (arr.length == 2) {
                                String date = arr[0].replace(":", "-");
                                String dateTime = String.format("%s %s", date, arr[1]);
                                camPhoto.setShotAt(dateTime);
                            }
                            break;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return camPhoto;
    }
}
