/*
 * 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.jpos.fiscalprinter;

/**
 *
 * @author V.Kravtsov
 */
// java
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 PrinterImage implements JposConst {

    private int startLine = 1;                  // image start line
    private int imageWidth = 0;                 // image width
    private int imageHeight = 0;                // image height
    private String fileName = "";               // image file name
    private byte[][] lines = new byte[0][0];    // image data
    private static Logger logger = Logger.getLogger(PrinterImage.class);

    /** Creates a new instance of PrinterImage */
    public PrinterImage() {
    }

    public int getLastLine() {
        return startLine + imageHeight;
    }

    // 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);
    }

    // load image from file
    private void loadImage(int firstLine, String fileName, FiscalPrinterImpl service)
            throws Exception {
        BufferedImage image;
        File file = new File(fileName);
        image = BMPDecoder.read(file);

        // check max image width
        if (image.getWidth() > service.getMaxGraphicsWidth()) {
            throw new Exception(
                    Localizer.getString(Localizer.InvalidImageWidth) + ", "
                    + String.valueOf(image.getWidth()) + " > "
                    + String.valueOf(service.getMaxGraphicsWidth()));
        }
        // check max image height
        int height = firstLine + image.getHeight();
        if (height > service.getMaxGraphicsHeight()) {
            throw new Exception(
                    Localizer.getString(Localizer.InvalidImageHeight) + ", "
                    + String.valueOf(height) + " > "
                    + String.valueOf(service.getMaxGraphicsHeight()));
        }
        image = ImageUtils.indexToDirectColorModel(image);

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

        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]);
        }
    }

    private void centerImage(int graphicsWidth) {
        int offset = (graphicsWidth - imageWidth) / 16;
        for (int i = 0; i < imageHeight; i++) {
            byte[] b = new byte[offset + lines[i].length];
            Arrays.fill(b, (byte) 0);
            for (int j = 0; j < lines[i].length; j++) {
                b[offset + j] = lines[i][j];
            }
            lines[i] = b;
        }
    }

    public void print(FiscalPrinterImpl service)
            throws Exception {
        service.printGraphics(startLine + 1, startLine + imageHeight);
    }

    public void load(String fileName, int firstLine, FiscalPrinterImpl service)
            throws Exception {
        loadImage(firstLine, fileName, service);
        if (service.centerImage) {
            centerImage(service.getMaxGraphicsWidth());
        }
        startLine = firstLine;
        // write image to device
        for (int i = 0; i < imageHeight; i++) {
            service.loadGraphics(startLine + i, imageHeight, lines[i]);
        }
        this.fileName = fileName;
    }

    public void save(String prefix, JposEntry jposEntry)
            throws Exception {
        jposEntry.addProperty(prefix + "FirstLine", new Integer(startLine));
        jposEntry.addProperty(prefix + "Height", new Integer(imageHeight));
    }

    public void clear()
            throws Exception {
        startLine = 0;
        imageHeight = 0;
    }

    public boolean load(String prefix, JposEntry jposEntry)
            throws Exception {
        if (!jposEntry.hasPropertyWithName(prefix + "FirstLine")) {
            return false;
        }

        if (!jposEntry.hasPropertyWithName(prefix + "Height")) {
            return false;
        }

        String propName = prefix + "FirstLine";
        startLine = ((Integer) jposEntry.getPropertyValue(propName)).intValue();
        if (!PrintGraphicsEx.validLine(startLine)) 
        {
            return false;
        }

        propName = prefix + "Height";
        imageHeight = ((Integer) jposEntry.getPropertyValue(propName)).intValue();
        if (!validHeight(imageHeight)) 
        {
            return false;
        }
        
        int endline = startLine + imageHeight;
        if (!PrintGraphicsEx.validLine(endline))
        {
            return false;
        }
        
        return true;
    }

    public boolean validHeight(int height)
    {
        return (height > 0);
    }
            
    public int getHeight() {
        return imageHeight;
    }
}
