// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
package common;

import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.util.Arrays;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

import streamer.BaseElement;
import streamer.ByteBuffer;
import streamer.Element;
import streamer.Link;

public class BufferedImagePixelsAdapter extends BaseElement {
    protected static Logger LOGGER = LogManager.getLogger(BufferedImagePixelsAdapter.class);

    public static final String TARGET_X = "x";
    public static final String TARGET_Y = "y";
    public static final String WIDTH = "width";
    public static final String HEIGHT = "height";
    public static final String RGB888LE32 = "RGB888LE32";
    public static final String PIXEL_FORMAT = "pixel_format";

    protected BufferedImageCanvas canvas;

    public BufferedImagePixelsAdapter(String id, BufferedImageCanvas canvas) {
        super(id);
        this.canvas = canvas;
        declarePads();
    }

    private void declarePads() {
        inputPads.put(STDIN, null);
    }

    @Override
    public String toString() {
        return "Renderer(" + id + ")";
    }

    @Override
    public void handleData(ByteBuffer buf, Link link) {
        if (verbose)
            LOGGER.debug("[" + this + "] INFO: Data received: " + buf + ".");

        int x = (Integer)buf.getMetadata(TARGET_X);
        int y = (Integer)buf.getMetadata(TARGET_Y);
        int rectWidth = (Integer)buf.getMetadata(WIDTH);
        int rectHeight = (Integer)buf.getMetadata(HEIGHT);
        String format = (String)buf.getMetadata(PIXEL_FORMAT);

        int bpp;
        // Support RGB888/32 little endian only
        if (format != null && RGB888LE32.equals(format)) {
            bpp = 4;
            // TODO: support more formats
        } else
            throw new RuntimeException("Unsupported format: " + format + ". Supported formats: " + RGB888LE32 + ".");

        int dataLength = rectWidth * rectHeight * bpp;
        if (!cap(buf, dataLength, dataLength, link, false))
            return;

        // Draw rectangle on offline buffer
        BufferedImage image = canvas.getOfflineImage();

        DataBuffer dataBuf = image.getRaster().getDataBuffer();

        switch (dataBuf.getDataType()) {

        case DataBuffer.TYPE_INT: {

            // Convert array of bytes to array of int's
            int[] intArray = buf.toIntLEArray();

            // We chose RGB888 model, so Raster will use DataBufferInt type
            DataBufferInt dataBuffer = (DataBufferInt)dataBuf;

            int imageWidth = image.getWidth();
            int imageHeight = image.getHeight();

            // Paint rectangle directly on buffer, line by line
            int[] imageBuffer = dataBuffer.getData();

            for (int srcLine = 0, dstLine = y; srcLine < rectHeight && dstLine < imageHeight; srcLine++, dstLine++) {
                try {
                    System.arraycopy(intArray, srcLine * rectWidth, imageBuffer, x + dstLine * imageWidth, rectWidth);
                } catch (IndexOutOfBoundsException e) {
                    LOGGER.info("[ignored] copy error",e);
                }
            }
            break;
        }

        default:
            throw new RuntimeException("Unsupported data buffer in buffered image: expected data buffer of type int (DataBufferInt). Actual data buffer type: "
                    + dataBuf.getClass().getSimpleName());
        }

        // Request update of repainted area
        canvas.repaint(x, y, rectWidth, rectHeight);

        buf.unref();
    }

    public static void main(String args[]) {
        System.setProperty("streamer.Element.debug", "true");

        BufferedImageCanvas canvas = new BufferedImageCanvas(4, 4);

        Element renderer = new BufferedImagePixelsAdapter("renderer", canvas);

        byte[] pixels = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5,
                6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};

        int[] pixelsLE = new int[] {0x04030201, 0x08070605, 0x0c0b0a09, 0x100f0e0d, 0x04030201, 0x08070605, 0x0c0b0a09, 0x100f0e0d, 0x04030201, 0x08070605,
                0x0c0b0a09, 0x100f0e0d, 0x04030201, 0x08070605, 0x0c0b0a09, 0x100f0e0d};

        ByteBuffer buf = new ByteBuffer(pixels);
        buf.putMetadata(TARGET_X, 0);
        buf.putMetadata(TARGET_Y, 0);
        buf.putMetadata(WIDTH, 4);
        buf.putMetadata(HEIGHT, 4);
        buf.putMetadata(PIXEL_FORMAT, RGB888LE32);

        renderer.handleData(buf, null);

        String actualData = Arrays.toString(((DataBufferInt)canvas.getOfflineImage().getRaster().getDataBuffer()).getData());
        String expectedData = Arrays.toString(pixelsLE);
        if (!actualData.equals(expectedData))
            LOGGER.error("Actual image:   " + actualData + "\nExpected image: " + expectedData + ".");

    }

}
