package io.lumify.core.model.artifactThumbnails;

import com.altamiracorp.bigtable.model.ModelSession;
import com.altamiracorp.bigtable.model.Repository;
import com.altamiracorp.bigtable.model.Row;
import io.lumify.core.config.Configuration;
import io.lumify.core.exception.LumifyResourceNotFoundException;
import io.lumify.core.user.User;
import io.lumify.core.util.LumifyLogger;
import io.lumify.core.util.LumifyLoggerFactory;
import org.securegraph.Vertex;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

public abstract class ArtifactThumbnailRepository extends Repository<BigTableArtifactThumbnail> {
    private static final LumifyLogger LOGGER = LumifyLoggerFactory.getLogger(ArtifactThumbnailRepository.class);
    public static int FRAMES_PER_PREVIEW = 20;
    public static int PREVIEW_FRAME_WIDTH = 360;
    public static int PREVIEW_FRAME_HEIGHT = 240;
    private final String yAxisFlipNeededPropertyIri;
    private final String cwRotationNeededPropertyIri;

    public ArtifactThumbnailRepository(ModelSession modelSession, final Configuration configuration) {
        super(modelSession);
        this.yAxisFlipNeededPropertyIri = configuration.get("ontology.iri.yAxisFlipNeeded", null);
        this.cwRotationNeededPropertyIri = configuration.get("ontology.iri.cwRotationNeeded", null);
    }

    public abstract BigTableArtifactThumbnail fromRow(Row row);

    public abstract Row toRow(BigTableArtifactThumbnail artifactThumbnail);

    public abstract String getTableName();

    public abstract ArtifactThumbnail getThumbnail(Object artifactVertexId, String thumbnailType, int width, int height, User user);

    public abstract byte[] getThumbnailData(Object artifactVertexId, String thumbnailType, int width, int height, User user);

    public abstract ArtifactThumbnail createThumbnail(Vertex artifactVertex, String thumbnailType, InputStream in, int[] boundaryDims, User user) throws IOException;

    public ArtifactThumbnail generateThumbnail(Vertex artifactVertex, InputStream in, int[] boundaryDims) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        String format;
        int type;
        try {
            BufferedImage originalImage = ImageIO.read(in);
            type = ImageUtils.thumbnailType(originalImage);
            format = ImageUtils.thumbnailFormat(originalImage);

            int cwRotationNeeded = 0;
            if (cwRotationNeededPropertyIri != null) {
                Integer nullable = (Integer) artifactVertex.getPropertyValue(cwRotationNeededPropertyIri);
                if (nullable != null) {
                    cwRotationNeeded = nullable;
                }
            }
            boolean yAxisFlipNeeded = false;
            if (yAxisFlipNeededPropertyIri != null) {
                Boolean nullable = (Boolean) artifactVertex.getPropertyValue(yAxisFlipNeededPropertyIri);
                if (nullable != null) {
                    yAxisFlipNeeded = nullable;
                }
            }

            //Rotate and flip image.
            BufferedImage transformedImage = ImageUtils.reOrientImage(originalImage, yAxisFlipNeeded, cwRotationNeeded);

            //Get new image dimensions, which will be used for the icon.
            int[] transformedImageDims = new int[]{transformedImage.getWidth(), transformedImage.getHeight()};
            int[] newImageDims = getScaledDimension(transformedImageDims, boundaryDims);
            if (newImageDims[0] >= transformedImageDims[0] || newImageDims[1] >= transformedImageDims[1]) {
                LOGGER.info("Original image dimensions %d x %d are smaller "
                                + "than requested dimensions %d x %d returning original.",
                        transformedImageDims[0], transformedImageDims[1],
                        newImageDims[0], newImageDims[1]);
            }


            //Resize the image.
            BufferedImage resizedImage = new BufferedImage(newImageDims[0], newImageDims[1], type);
            Graphics2D g = resizedImage.createGraphics();
            if (transformedImage.getColorModel().getNumComponents() > 3) {
                g.drawImage(transformedImage, 0, 0, resizedImage.getWidth(), resizedImage.getHeight(), null);
            } else {
                g.drawImage(transformedImage, 0, 0, resizedImage.getWidth(), resizedImage.getHeight(), Color.BLACK, null);
            }
            g.dispose();

            //Write the bufferedImage to a file.
            ImageIO.write(resizedImage, format, out);
        } catch (IOException e) {
            throw new LumifyResourceNotFoundException("Error reading inputstream");
        }
        return new ArtifactThumbnail(out.toByteArray(), type, format);
    }

    public int[] getScaledDimension(int[] imgSize, int[] boundary) {
        int originalWidth = imgSize[0];
        int originalHeight = imgSize[1];
        int boundWidth = boundary[0];
        int boundHeight = boundary[1];
        int newWidth = originalWidth;
        int newHeight = originalHeight;

        if (originalWidth > boundWidth) {
            newWidth = boundWidth;
            newHeight = (newWidth * originalHeight) / originalWidth;
        }

        if (newHeight > boundHeight) {
            newHeight = boundHeight;
            newWidth = (newHeight * originalWidth) / originalHeight;
        }

        return new int[]{newWidth, newHeight};
    }
}

@@ -1026,30 +1026,19 @@
 AxisFlip
-NeededProperty
+ped
 Iri;%0A   
@@ -1060,39 +1060,32 @@
 String c
-wRotationNeededProperty
+lockwiseRotation
 Iri;%0A%0A  
@@ -1232,38 +1232,27 @@
 is.yAxisFlip
-NeededProperty
+ped
 Iri = config
@@ -1277,16 +1277,22 @@
 ogy.iri.
+media.
 yAxisFli
@@ -1292,20 +1292,17 @@
 AxisFlip
-Need
+p
 ed%22, nul
@@ -1319,39 +1319,32 @@
   this.c
-wRotationNeededProperty
+lockwiseRotation
 Iri = co
@@ -1373,26 +1373,39 @@
 ogy.iri.
-cw
+media.clockwise
 Rotation
 Needed%22,
@@ -1396,22 +1396,16 @@
 Rotation
-Needed
 %22, null)
@@ -2495,39 +2495,32 @@
    if (c
-wRotationNeededProperty
+lockwiseRotation
 Iri != n
@@ -2608,31 +2608,24 @@
 ue(c
-wRotationNeededProperty
+lockwiseRotation
 Iri)
@@ -2817,30 +2817,19 @@
 AxisFlip
-NeededProperty
+ped
 Iri != n
@@ -2925,22 +2925,11 @@
 Flip
-NeededProperty
+ped
 Iri)

use new config key that contains media