/*
 *  Licensed 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.
 *  under the License.
 */

package org.apache.commons.imaging.formats.wbmp;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.imaging.ImageFormat;
import org.apache.commons.imaging.ImageFormats;
import org.apache.commons.imaging.ImageInfo;
import org.apache.commons.imaging.ImageParser;
import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.ImageWriteException;
import org.apache.commons.imaging.common.IImageMetadata;
import org.apache.commons.imaging.common.bytesource.ByteSource;
import org.apache.commons.imaging.util.IoUtils;

public class WbmpImageParser extends ImageParser {
    public WbmpImageParser() {
    }

    @Override
    public String getName() {
        return "Wbmp-Custom";
    }

    @Override
    public String getDefaultExtension() {
        return DEFAULT_EXTENSION;
    }

    private static final String DEFAULT_EXTENSION = ".wbmp";
    private static final String ACCEPTED_EXTENSIONS[] = { ".wbmp", };

    @Override
    protected String[] getAcceptedExtensions() {
        return ACCEPTED_EXTENSIONS;
    }

    @Override
    protected ImageFormat[] getAcceptedTypes() {
        return new ImageFormat[] { ImageFormats.WBMP, //
        };
    }

    @Override
    public boolean embedICCProfile(final File src, final File dst, final byte profile[]) {
        return false;
    }

    @Override
    public IImageMetadata getMetadata(final ByteSource byteSource, final Map<String,Object> params)
            throws ImageReadException, IOException {
        return null;
    }

    @Override
    public ImageInfo getImageInfo(final ByteSource byteSource, final Map<String,Object> params)
            throws ImageReadException, IOException {
        final WbmpHeader wbmpHeader = readWbmpHeader(byteSource);
        return new ImageInfo("WBMP", 1, new ArrayList<String>(),
                ImageFormats.WBMP,
                "Wireless Application Protocol Bitmap", wbmpHeader.height,
                "image/vnd.wap.wbmp", 1, 0, 0, 0, 0, wbmpHeader.width, false,
                false, false, ImageInfo.COLOR_TYPE_BW,
                ImageInfo.COMPRESSION_ALGORITHM_NONE);
    }

    @Override
    public Dimension getImageSize(final ByteSource byteSource, final Map<String,Object> params)
            throws ImageReadException, IOException {
        final WbmpHeader wbmpHeader = readWbmpHeader(byteSource);
        return new Dimension(wbmpHeader.width, wbmpHeader.height);
    }

    @Override
    public byte[] getICCProfileBytes(final ByteSource byteSource, final Map<String,Object> params)
            throws ImageReadException, IOException {
        return null;
    }

    static class WbmpHeader {
        int typeField;
        byte fixHeaderField;
        int width;
        int height;

        public WbmpHeader(final int typeField, final byte fixHeaderField, final int width,
                final int height) {
            this.typeField = typeField;
            this.fixHeaderField = fixHeaderField;
            this.width = width;
            this.height = height;
        }

        public void dump(final PrintWriter pw) {
            pw.println("WbmpHeader");
            pw.println("TypeField: " + typeField);
            pw.println("FixHeaderField: 0x"
                    + Integer.toHexString(0xff & fixHeaderField));
            pw.println("Width: " + width);
            pw.println("Height: " + height);
        }
    }

    private int readMultiByteInteger(final InputStream is) throws ImageReadException,
            IOException {
        int value = 0;
        int nextByte;
        int totalBits = 0;
        do {
            nextByte = readByte("Header", is, "Error reading WBMP header");
            value <<= 7;
            value |= nextByte & 0x7f;
            totalBits += 7;
            if (totalBits > 31) {
                throw new ImageReadException(
                        "Overflow reading WBMP multi-byte field");
            }
        } while ((nextByte & 0x80) != 0);
        return value;
    }

    private void writeMultiByteInteger(final OutputStream os, final int value)
            throws IOException {
        boolean wroteYet = false;
        for (int position = 4 * 7; position > 0; position -= 7) {
            final int next7Bits = 0x7f & (value >>> position);
            if (next7Bits != 0 || wroteYet) {
                os.write(0x80 | next7Bits);
                wroteYet = true;
            }
        }
        os.write(0x7f & value);
    }

    private WbmpHeader readWbmpHeader(final ByteSource byteSource)
            throws ImageReadException, IOException {
        InputStream is = null;
        boolean canThrow = false;
        try {
            is = byteSource.getInputStream();
            final WbmpHeader ret = readWbmpHeader(is);
            canThrow = true;
            return ret;
        } finally {
            IoUtils.closeQuietly(canThrow, is);
        }
    }

    private WbmpHeader readWbmpHeader(final InputStream is)
            throws ImageReadException, IOException {
        final int typeField = readMultiByteInteger(is);
        if (typeField != 0) {
            throw new ImageReadException("Invalid/unsupported WBMP type "
                    + typeField);
        }

        final byte fixHeaderField = readByte("FixHeaderField", is,
                "Invalid WBMP File");
        if ((fixHeaderField & 0x9f) != 0) {
            throw new ImageReadException(
                    "Invalid/unsupported WBMP FixHeaderField 0x"
                            + Integer.toHexString(0xff & fixHeaderField));
        }

        final int width = readMultiByteInteger(is);

        final int height = readMultiByteInteger(is);

        return new WbmpHeader(typeField, fixHeaderField, width, height);
    }

    @Override
    public boolean dumpImageFile(final PrintWriter pw, final ByteSource byteSource)
            throws ImageReadException, IOException {
        readWbmpHeader(byteSource).dump(pw);
        return true;
    }

    private BufferedImage readImage(final WbmpHeader wbmpHeader, final InputStream is)
            throws IOException {
        final int rowLength = (wbmpHeader.width + 7) / 8;
        final byte[] image = readBytes("Pixels", is,
                rowLength * wbmpHeader.height, "Error reading image pixels");
        final DataBufferByte dataBuffer = new DataBufferByte(image, image.length);
        final WritableRaster raster = Raster.createPackedRaster(dataBuffer,
                wbmpHeader.width, wbmpHeader.height, 1, null);
        final int[] palette = { 0x000000, 0xffffff };
        final IndexColorModel colorModel = new IndexColorModel(1, 2, palette, 0,
                false, -1, DataBuffer.TYPE_BYTE);
        return new BufferedImage(colorModel, raster,
                colorModel.isAlphaPremultiplied(), new Properties());
    }

    @Override
    public final BufferedImage getBufferedImage(final ByteSource byteSource,
            final Map<String,Object> params) throws ImageReadException, IOException {
        InputStream is = null;
        boolean canThrow = false;
        try {
            is = byteSource.getInputStream();
            final WbmpHeader wbmpHeader = readWbmpHeader(is);
            final BufferedImage ret = readImage(wbmpHeader, is);
            canThrow = true;
            return ret;
        } finally {
            IoUtils.closeQuietly(canThrow, is);
        }
    }

    @Override
    public void writeImage(final BufferedImage src, final OutputStream os, Map<String,Object> params)
            throws ImageWriteException, IOException {
        // make copy of params; we'll clear keys as we consume them.
        params = (params == null) ? new HashMap<String,Object>() : new HashMap<String,Object>(params);

        // clear format key.
        if (params.containsKey(PARAM_KEY_FORMAT)) {
            params.remove(PARAM_KEY_FORMAT);
        }

        if (params.size() > 0) {
            final Object firstKey = params.keySet().iterator().next();
            throw new ImageWriteException("Unknown parameter: " + firstKey);
        }

        writeMultiByteInteger(os, 0); // typeField
        os.write(0); // fixHeaderField
        writeMultiByteInteger(os, src.getWidth());
        writeMultiByteInteger(os, src.getHeight());

        for (int y = 0; y < src.getHeight(); y++) {
            int pixel = 0;
            int nextBit = 0x80;
            for (int x = 0; x < src.getWidth(); x++) {
                final int argb = src.getRGB(x, y);
                final int red = 0xff & (argb >> 16);
                final int green = 0xff & (argb >> 8);
                final int blue = 0xff & (argb >> 0);
                final int sample = (red + green + blue) / 3;
                if (sample > 127) {
                    pixel |= nextBit;
                }
                nextBit >>>= 1;
                if (nextBit == 0) {
                    os.write(pixel);
                    pixel = 0;
                    nextBit = 0x80;
                }
            }
            if (nextBit != 0x80) {
                os.write(pixel);
            }
        }
    }

    /**
     * Extracts embedded XML metadata as XML string.
     * <p>
     * 
     * @param byteSource
     *            File containing image data.
     * @param params
     *            Map of optional parameters, defined in ImagingConstants.
     * @return Xmp Xml as String, if present. Otherwise, returns null.
     */
    @Override
    public String getXmpXml(final ByteSource byteSource, final Map<String,Object> params)
            throws ImageReadException, IOException {
        return null;
    }
}
