/*

   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 org.apache.batik.transcoder.wmf.tosvg;

import java.awt.Paint;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.TexturePaint;
import java.awt.image.BufferedImage;
import java.awt.geom.*;
import java.util.Map;
import java.util.HashMap;

import org.apache.batik.transcoder.wmf.WMFConstants;

/**
 * This class generate Paints from WMF hatch definitions. All generated
 * Paints are cached for future use.
 *
 * @version $Id$
 */
public class TextureFactory {
    private static TextureFactory fac = null;
    private Map textures = new HashMap(1);
    private static final int SIZE = 10;
    private float scale = 1.0f;

    private TextureFactory(float scale) {
    }

    /** Get the unique instance of the class.
     */
    public static TextureFactory getInstance() {
        if (fac == null) fac = new TextureFactory(1.0f);
        return fac;
    }

    /** Get the unique instance of the class, setting the scale of the pattern.
     *  TODO : scale is not handled for now
     */
    public static TextureFactory getInstance(float scale) {
        if (fac == null) fac = new TextureFactory(scale);
        return fac;
    }

    /** Rest the factory. It empties all the previouly cached Paints are
     * disposed of.
     */
    public void reset() {
        textures.clear();
    }

    /** Get a texture from a WMF hatch definition (in black Color). This
     *  texture will be cached, so the Paint will only be created once.
     */
    public Paint getTexture(int textureId) {
        Integer _itexture = new Integer(textureId);
        if (textures.containsKey( _itexture)) {
            Paint paint = (Paint)(textures.get(_itexture));
            return paint;
        } else {
            Paint paint = createTexture(textureId, null, null);
            if (paint != null) textures.put(_itexture, paint);
            return paint;
        }
    }

    /** Get a texture from a WMF hatch definition, with a foreground color. This
     *  texture will be cached, so the Paint will only be created once.
     */
    public Paint getTexture(int textureId, Color foreground) {
        ColoredTexture _ctexture = new ColoredTexture(textureId, foreground, null);
        if (textures.containsKey(_ctexture)) {
            Paint paint = (Paint)(textures.get(_ctexture));
            return paint;
        } else {
            Paint paint = createTexture(textureId, foreground, null);
            if (paint != null) textures.put(_ctexture, paint);
            return paint;
        }
    }

    /** Get a texture from a WMF hatch definition, with a foreground and a
     *  background color. This texture will be cached, so the Paint will
     * only be created once.
     */
    public Paint getTexture(int textureId, Color foreground, Color background) {
        ColoredTexture _ctexture = new ColoredTexture(textureId, foreground, background);
        if (textures.containsKey(_ctexture)) {
            Paint paint = (Paint)(textures.get(_ctexture));
            return paint;
        } else {
            Paint paint = createTexture(textureId, foreground, background);
            if (paint != null) textures.put(_ctexture, paint);
            return paint;
        }
    }

    /** Called internally if the Paint does not exist in the cache and must
     *  be created.
     */
    private Paint createTexture(int textureId, Color foreground, Color background) {
        BufferedImage img = new BufferedImage(SIZE, SIZE, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = img.createGraphics();
        Rectangle2D rec = new Rectangle2D.Float(0, 0, SIZE, SIZE);
        Paint paint = null;
        boolean ok = false;
        if (background != null) {
            g2d.setColor(background);
            g2d.fillRect(0, 0, SIZE, SIZE);
        }
        if (foreground == null) g2d.setColor(Color.black);
        else g2d.setColor(foreground);

        if (textureId == WMFConstants.HS_VERTICAL) {
            for (int i = 0; i < 5; i++) {
                g2d.drawLine(i*10, 0, i*10, SIZE);
            }
            ok = true;
        } else if (textureId == WMFConstants.HS_HORIZONTAL) {
            for (int i = 0; i < 5; i++) {
                g2d.drawLine(0, i*10, SIZE, i*10);
            }
            ok = true;
        } else if (textureId == WMFConstants.HS_BDIAGONAL) {
            for (int i = 0; i < 5; i++) {
                g2d.drawLine(0, i*10, i*10, 0);
            }
            ok = true;
        } else if (textureId == WMFConstants.HS_FDIAGONAL) {
            for (int i = 0; i < 5; i++) {
                g2d.drawLine(0, i*10, SIZE - i*10, SIZE);
            }
            ok = true;
        } else if (textureId == WMFConstants.HS_DIAGCROSS) {
            for (int i = 0; i < 5; i++) {
                g2d.drawLine(0, i*10, i*10, 0);
                g2d.drawLine(0, i*10, SIZE - i*10, SIZE);
            }
            ok = true;
        } else if (textureId == WMFConstants.HS_CROSS) {
            for (int i = 0; i < 5; i++) {
                g2d.drawLine(i*10, 0, i*10, SIZE);
                g2d.drawLine(0, i*10, SIZE, i*10);
            }
            ok = true;
        }
        img.flush();
        if (ok) paint = new TexturePaint(img, rec);
        return paint;
    }

    /** Contain a handle to a Colored texture, with optional foreground and
     * background colors.
     */
    private class ColoredTexture {

        final int textureId;
        final Color foreground;
        final Color background;

        ColoredTexture(int textureId, Color foreground, Color background) {
            this.textureId = textureId;
            this.foreground = foreground;
            this.background = background;
        }
    }
}
