/*
 * 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.
 */

/* $Id$ */

package org.apache.fop.render.afp;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.EnumMap;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.fop.afp.AFPConstants;
import org.apache.fop.afp.AFPDataObjectInfo;
import org.apache.fop.afp.AFPEventProducer;
import org.apache.fop.afp.AFPResourceLevel;
import org.apache.fop.afp.AFPResourceLevelDefaults;
import org.apache.fop.afp.modca.triplets.MappingOptionTriplet;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.apps.io.InternalResourceResolver;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.render.RendererConfig;
import org.apache.fop.render.afp.AFPFontConfig.AFPFontInfoConfigParser;
import org.apache.fop.util.LogUtil;

import static org.apache.fop.render.afp.AFPRendererConfig.ImagesModeOptions.MODE_COLOR;
import static org.apache.fop.render.afp.AFPRendererConfig.ImagesModeOptions.MODE_GRAYSCALE;
import static org.apache.fop.render.afp.AFPRendererOption.DEFAULT_RESOURCE_LEVELS;
import static org.apache.fop.render.afp.AFPRendererOption.GOCA;
import static org.apache.fop.render.afp.AFPRendererOption.GOCA_TEXT;
import static org.apache.fop.render.afp.AFPRendererOption.IMAGES;
import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_DITHERING_QUALITY;
import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_FS45;
import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_JPEG;
import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_MAPPING_OPTION;
import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_MODE;
import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_NATIVE;
import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_WRAP_PSEG;
import static org.apache.fop.render.afp.AFPRendererOption.JPEG_ALLOW_JPEG_EMBEDDING;
import static org.apache.fop.render.afp.AFPRendererOption.JPEG_BITMAP_ENCODING_QUALITY;
import static org.apache.fop.render.afp.AFPRendererOption.LINE_WIDTH_CORRECTION;
import static org.apache.fop.render.afp.AFPRendererOption.RENDERER_RESOLUTION;
import static org.apache.fop.render.afp.AFPRendererOption.RESOURCE_GROUP_URI;
import static org.apache.fop.render.afp.AFPRendererOption.SHADING;

/**
 * The AFP renderer config object.
 */
public final class AFPRendererConfig implements RendererConfig {

    /**
     * An enumeration for the various images modes available to the AFP renderer.
     */
    public enum ImagesModeOptions {

        MODE_GRAYSCALE("b+w", "bits-per-pixel"),
        MODE_COLOR("color", "cmyk");

        private final String name;

        private final String modeAttribute;

        private ImagesModeOptions(String name, String modeAttribute) {
            this.name = name;
            this.modeAttribute = modeAttribute;
        }

        public String getName() {
            return name;
        }

        public String getModeAttribute() {
            return modeAttribute;
        }

        public static ImagesModeOptions forName(String name) {
            for (ImagesModeOptions option : values()) {
                if (option.name.equals(name)) {
                    return option;
                }
            }
            throw new IllegalArgumentException(name);
        }
    }

    private final EnumMap<AFPRendererOption, Object> params
            = new EnumMap<AFPRendererOption, Object>(AFPRendererOption.class);

    private final EnumMap<ImagesModeOptions, Object> imageModeParams
    = new EnumMap<ImagesModeOptions, Object>(ImagesModeOptions.class);

    private final AFPFontConfig fontConfig;

    private AFPRendererConfig(AFPFontConfig fontConfig) {
        this.fontConfig = fontConfig;
    }

    public AFPFontConfig getFontInfoConfig() {
        return fontConfig;
    }

    public Boolean isColorImages() {
        return getParam(IMAGES_MODE, Boolean.class);
    }

    public Boolean isCmykImagesSupported() {
        if (!isColorImages()) {
            throw new IllegalStateException();
        }
        return Boolean.class.cast(imageModeParams.get(MODE_COLOR));
    }

    public Integer getBitsPerPixel() {
        if (isColorImages()) {
            throw new IllegalStateException();
        }
        return Integer.class.cast(imageModeParams.get(MODE_GRAYSCALE));
    }

    public Float getDitheringQuality() {
        return getParam(IMAGES_DITHERING_QUALITY, Float.class);
    }

    public Boolean isNativeImagesSupported() {
        return getParam(IMAGES_NATIVE, Boolean.class);
    }

    public AFPShadingMode getShadingMode() {
        return getParam(SHADING, AFPShadingMode.class);
    }

    public Integer getResolution() {
        return getParam(RENDERER_RESOLUTION, Integer.class);
    }


    public URI getDefaultResourceGroupUri() {
        return getParam(RESOURCE_GROUP_URI, URI.class);
    }

    public AFPResourceLevelDefaults getResourceLevelDefaults() {
        return getParam(DEFAULT_RESOURCE_LEVELS, AFPResourceLevelDefaults.class);
    }

    public Boolean isWrapPseg() {
        return getParam(IMAGES_WRAP_PSEG, Boolean.class);
    }

    public Boolean isFs45() {
        return getParam(IMAGES_FS45, Boolean.class);
    }

    public Boolean allowJpegEmbedding() {
        return getParam(JPEG_ALLOW_JPEG_EMBEDDING, Boolean.class);
    }

    public Float getBitmapEncodingQuality() {
        return getParam(JPEG_BITMAP_ENCODING_QUALITY, Float.class);
    }

    public Float getLineWidthCorrection() {
        return getParam(LINE_WIDTH_CORRECTION, Float.class);
    }

    public Boolean isGocaEnabled() {
        return getParam(GOCA, Boolean.class);
    }

    public Boolean isStrokeGocaText() {
        return getParam(GOCA_TEXT, Boolean.class);
    }

    private <T> T getParam(AFPRendererOption options, Class<T> type) {
        assert options.getType().equals(type);
        return type.cast(params.get(options));
    }

    private <T> void setParam(AFPRendererOption option, T value) {
        assert option.getType().isInstance(value);
        params.put(option, value);
    }

    /**
     * The parser for AFP renderer specific data in the FOP conf.
     */
    public static final class AFPRendererConfigParser implements RendererConfigParser {

        private static final Log LOG = LogFactory.getLog(AFPRendererConfigParser.class);

        /** {@inheritDoc} */
        public AFPRendererConfig build(FOUserAgent userAgent, Configuration cfg) throws FOPException {
            boolean strict = userAgent.validateUserConfigStrictly();
            AFPRendererConfig config = null;
            AFPEventProducer eventProducer = AFPEventProducer.Provider.get(userAgent.getEventBroadcaster());
            try {
                config = new ParserHelper(cfg, userAgent.getFontManager(), strict, eventProducer).config;
            } catch (ConfigurationException e) {
                LogUtil.handleException(LOG, e, strict);
            }
            return config;
        }

        /** {@inheritDoc} */
        public String getMimeType() {
            return MimeConstants.MIME_AFP;
        }
    }

    private static final class ParserHelper {

        private static final Log LOG = LogFactory.getLog(ParserHelper.class);

        private final AFPRendererConfig config;

        private final boolean strict;

        private final Configuration cfg;

        private ParserHelper(Configuration cfg, FontManager fontManager, boolean strict,
                AFPEventProducer eventProducer)
                        throws ConfigurationException, FOPException {
            this.cfg = cfg;
            this.strict = strict;
            if (cfg != null) {
                config = new AFPRendererConfig(new AFPFontInfoConfigParser().parse(cfg,
                        fontManager, strict, eventProducer));
                configure();
            } else {
                config = new AFPRendererConfig(new AFPFontInfoConfigParser().getEmptyConfig());
            }
        }

        private void configure() throws ConfigurationException, FOPException {
            configureImages();
            setParam(SHADING, AFPShadingMode.getValueOf(
                    cfg.getChild(SHADING.getName()).getValue(AFPShadingMode.COLOR.getName())));
            Configuration rendererResolutionCfg = cfg.getChild(RENDERER_RESOLUTION.getName(), false);
            setParam(RENDERER_RESOLUTION, rendererResolutionCfg == null ? 240
                    : rendererResolutionCfg.getValueAsInteger(240));
            Configuration lineWidthCorrectionCfg = cfg.getChild(LINE_WIDTH_CORRECTION.getName(),
                    false);
            setParam(LINE_WIDTH_CORRECTION, lineWidthCorrectionCfg != null
                    ? lineWidthCorrectionCfg.getValueAsFloat()
                    : AFPConstants.LINE_WIDTH_CORRECTION);
            Configuration gocaCfg = cfg.getChild(GOCA.getName());
            boolean gocaEnabled = gocaCfg.getAttributeAsBoolean("enabled", true);
            setParam(GOCA, gocaEnabled);
            String strokeGocaText = gocaCfg.getAttribute(GOCA_TEXT.getName(), "default");
            setParam(GOCA_TEXT, "stroke".equalsIgnoreCase(strokeGocaText)
                            || "shapes".equalsIgnoreCase(strokeGocaText));
            //TODO remove
            createResourceGroupFile();
            createResourceLevel();
        }

        private void setParam(AFPRendererOption option, Object value) {
            config.setParam(option, value);
        }

        private void configureImages() throws ConfigurationException, FOPException {
            Configuration imagesCfg = cfg.getChild(IMAGES.getName());
            ImagesModeOptions imagesMode = ImagesModeOptions.forName(imagesCfg.getAttribute(
                    IMAGES_MODE.getName(), MODE_GRAYSCALE.getName()));
            boolean colorImages = MODE_COLOR == imagesMode;
            setParam(IMAGES_MODE, colorImages);
            if (colorImages) {
                config.imageModeParams.put(MODE_COLOR, imagesCfg
                        .getAttributeAsBoolean(imagesMode.getModeAttribute(), false));
            } else {
                config.imageModeParams.put(MODE_GRAYSCALE,
                        imagesCfg.getAttributeAsInteger(imagesMode.getModeAttribute(), 8));
            }
            String dithering = imagesCfg.getAttribute(AFPRendererOption.IMAGES_DITHERING_QUALITY.getName(), "medium");
            float dq;
            if (dithering.startsWith("min")) {
                dq = 0.0f;
            } else if (dithering.startsWith("max")) {
                dq = 1.0f;
            } else {
                try {
                    dq = Float.parseFloat(dithering);
                } catch (NumberFormatException nfe) {
                    //Default value
                    dq = 0.5f;
                }
            }
            setParam(IMAGES_DITHERING_QUALITY, dq);
            setParam(IMAGES_NATIVE, imagesCfg.getAttributeAsBoolean(IMAGES_NATIVE.getName(), false));
            setParam(IMAGES_WRAP_PSEG,
                    imagesCfg.getAttributeAsBoolean(IMAGES_WRAP_PSEG.getName(), false));
            setParam(IMAGES_FS45, imagesCfg.getAttributeAsBoolean(IMAGES_FS45.getName(), false));
            if ("scale-to-fit".equals(imagesCfg.getAttribute(IMAGES_MAPPING_OPTION.getName(), null))) {
                setParam(IMAGES_MAPPING_OPTION, MappingOptionTriplet.SCALE_TO_FILL);
            } else {
                setParam(IMAGES_MAPPING_OPTION, AFPDataObjectInfo.DEFAULT_MAPPING_OPTION);
            }
            configureJpegImages(imagesCfg);
        }

        private void configureJpegImages(Configuration imagesCfg) {
            Configuration jpegConfig = imagesCfg.getChild(IMAGES_JPEG.getName());
            float bitmapEncodingQuality = 1.0f;
            boolean allowJpegEmbedding = false;
            if (jpegConfig != null) {
                allowJpegEmbedding = jpegConfig.getAttributeAsBoolean(
                        JPEG_ALLOW_JPEG_EMBEDDING.getName(),
                        false);
                String bitmapEncodingQualityStr = jpegConfig.getAttribute(
                        JPEG_BITMAP_ENCODING_QUALITY.getName(), null);
                if (bitmapEncodingQualityStr != null) {
                    try {
                        bitmapEncodingQuality = Float.parseFloat(bitmapEncodingQualityStr);
                    } catch (NumberFormatException nfe) {
                        //ignore and leave the default above
                    }
                }
            }
            setParam(JPEG_BITMAP_ENCODING_QUALITY, bitmapEncodingQuality);
            setParam(JPEG_ALLOW_JPEG_EMBEDDING, allowJpegEmbedding);
        }

        private void createResourceGroupFile() throws FOPException {
            try {
                Configuration resourceGroupUriCfg = cfg.getChild(RESOURCE_GROUP_URI.getName(), false);
                if (resourceGroupUriCfg != null) {
                    URI resourceGroupUri = InternalResourceResolver.cleanURI(resourceGroupUriCfg.getValue());
                    setParam(RESOURCE_GROUP_URI, resourceGroupUri);
                }
            } catch (ConfigurationException e) {
                LogUtil.handleException(LOG, e, strict);
            } catch (URISyntaxException use) {
                LogUtil.handleException(LOG, use, strict);
            }
        }

        private void createResourceLevel() throws FOPException {
            Configuration defaultResourceLevelCfg = cfg.getChild(DEFAULT_RESOURCE_LEVELS.getName(), false);
            if (defaultResourceLevelCfg != null) {
                AFPResourceLevelDefaults defaults = new AFPResourceLevelDefaults();
                String[] types = defaultResourceLevelCfg.getAttributeNames();
                for (int i = 0, c = types.length; i < c; i++) {
                    String type = types[i];
                    try {
                        String level = defaultResourceLevelCfg.getAttribute(type);
                        defaults.setDefaultResourceLevel(type, AFPResourceLevel.valueOf(level));
                    } catch (IllegalArgumentException iae) {
                        LogUtil.handleException(LOG, iae, strict);
                    } catch (ConfigurationException e) {
                        LogUtil.handleException(LOG, e, strict);
                    }
                }
                setParam(DEFAULT_RESOURCE_LEVELS, defaults);
            }
        }
    }
}
