/*
 * PrinterImage.java
 *
 * Created on March 21 2008, 6:39
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package com.shtrih.fiscalprinter.command;

/**
 *
 * @author V.Kravtsov
 */
// javaimport com.shtrih.jpos.fiscalprinter.*;
import java.io.*;
import java.awt.*;
import java.util.*;
import java.awt.image.*;
// jpos
import jpos.*;
import jpos.config.*;
import net.sf.image4j.codec.bmp.*;
// apache
import org.apache.log4j.*;
// this
import com.shtrih.jpos.*;
import com.shtrih.util.*;
import com.shtrih.fiscalprinter.*;
import com.shtrih.fiscalprinter.command.*;


public class ImageLoader {

    private int firstLine = 0;
    private boolean centerImage = true;
    private final SMFiscalPrinter printer;
    private static Logger logger = Logger.getLogger(ImageLoader.class);

    /** Creates a new instance of PrinterImage */
    public ImageLoader(SMFiscalPrinter printer) {
        this.printer = printer;
    }

    public int getFirstLine() {
        return firstLine;
    }

    private boolean getCenterImage() {
        return centerImage;
    }

    public void setFirstLine(int value) {
        this.firstLine = value;
    }

    public void setCenterImage(boolean value) {
        this.centerImage = value;
    }

    // convert pixels to bits
    private byte[] pixelsToBits(int[] pixels) {
        BitSet bits = new BitSet(pixels.length);
        for (int i = 0; i < pixels.length; i++) {
            if (pixels[i] == 0) {
                bits.set(i);
            }
        }
        return BitUtils.toByteArray(bits);
    }

    public void load(String fileName)
            throws Exception 
    {
        InputStream is = new FileInputStream(new File(fileName));
        load(new BMPDecoder(is).getBufferedImage());
    }

    public void load(BufferedImage image)
            throws Exception {
        byte[][] data = convertImage(image);
        writeImageData(data);
    }

    public byte[][] convertImage(BufferedImage image)
            throws Exception {
        checkImageSize(image);
        /*
        if (centerImage) {
            int maxWidth = printer.getModel().getMaxGraphicsWidth();
            image = centerImage(image, maxWidth);
        }
         * 
         */
        image = indexToDirectColorModel(image);
        byte[][] result = imageToData(image);
        if (centerImage) {
            int maxWidth = printer.getModel().getMaxGraphicsWidth();
            centerImage(result, image.getWidth(), maxWidth);
        }
        return result;
    }
            
            
    private void checkImageSize(BufferedImage image)
            throws Exception {
        // check max image width
        int maxGraphicsWidth = printer.getModel().getMaxGraphicsWidth();
        if (image.getWidth() > maxGraphicsWidth) {
            throw new Exception(
                    Localizer.getString(Localizer.InvalidImageWidth) + ", "
                    + String.valueOf(image.getWidth()) + " > "
                    + String.valueOf(maxGraphicsWidth));
        }
        // check max image height
        int height = firstLine + image.getHeight();
        int maxImageHeight = printer.getModel().getMaxGraphicsHeight();
        if (height > maxImageHeight) {
            throw new Exception(
                    Localizer.getString(Localizer.InvalidImageHeight) + ", "
                    + String.valueOf(height) + " > "
                    + String.valueOf(maxImageHeight));
        }
    }

    public static BufferedImage indexToDirectColorModel(BufferedImage image) {
        BufferedImage result = new BufferedImage(image.getWidth(),
                image.getHeight(), BufferedImage.TYPE_BYTE_BINARY);

        Graphics2D g2 = result.createGraphics();
        g2.drawImage(image, null, null);
        return result;
    }

    public static BufferedImage centerImage(BufferedImage image, int width) {
        BufferedImage result = new BufferedImage(width,
                image.getHeight(), image.getType());

        if (image.getWidth() > width) {
            return image;
        }
        int xOffset = (width - image.getWidth()) / 2;

        Graphics2D g2 = result.createGraphics();
        g2.setBackground(Color.white);
        g2.drawImage(image, null, xOffset, 0);
        return result;
    }

    private void centerImage(byte[][] data, int imageWidth, int maxWidth) {
        int offset = (maxWidth - imageWidth) / 16;
        for (int i = 0; i < data.length; i++) {
            byte[] b = new byte[offset + data[i].length];
            Arrays.fill(b, (byte) 0);
            for (int j = 0; j < data[i].length; j++) {
                b[offset + j] = data[i][j];
            }
            data[i] = b;
        }
    }
    
    private byte[][] imageToData(BufferedImage image)
            throws Exception {
        int imageWidth = image.getWidth();
        int imageHeight = image.getHeight();

        byte[][] lines = new byte[imageHeight][];
        int[] pixels = new int[imageWidth];
        Raster raster = image.getData();
        for (int i = 0; i < imageHeight; i++) {
            raster.getPixels(0, i, image.getWidth(), 1, pixels);
            lines[i] = pixelsToBits(pixels);
            lines[i] = BitUtils.swap(lines[i]);
        }
        return lines;
    }

    private void writeImageData(byte[][] data)
            throws Exception {
        for (int i = 0; i < data.length; i++) {
            printer.loadImageData(firstLine + i, data[i]);
        }
    }
    
}
