/*

   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.parser;

import org.w3c.dom.Element;
import org.w3c.dom.svg.SVGLength;

/**
 * This class provides methods to convert SVG length and coordinate to
 * float in user units.
 *
 * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
 * @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a>
 * @version $Id$
 */
public abstract class UnitProcessor {

    /**
     * This constant represents horizontal lengths.
     */
    public static final short HORIZONTAL_LENGTH = 2;

    /**
     * This constant represents vertical lengths.
     */
    public static final short VERTICAL_LENGTH = 1;

    /**
     * This constant represents other lengths.
     */
    public static final short OTHER_LENGTH = 0;

    /**
     * precomputed square-root of 2.0
     */
    static final double SQRT2 = Math.sqrt( 2.0 );
    
    /**
     * No instance of this class is required.
     */
    protected UnitProcessor() { }


    /**
     * Returns the specified value with the specified direction in
     * objectBoundingBox units.
     *
     * @param s the value
     * @param attr the attribute name that represents the value
     * @param d the direction of the value
     * @param ctx the context used to resolve relative value
     */
    public static float svgToObjectBoundingBox(String s,
                                               String attr,
                                               short d,
                                               Context ctx)
        throws ParseException {
        LengthParser lengthParser = new LengthParser();
        UnitResolver ur = new UnitResolver();
        lengthParser.setLengthHandler(ur);
        lengthParser.parse(s);
        return svgToObjectBoundingBox(ur.value, ur.unit, d, ctx);
    }

    /**
     * Returns the specified value with the specified direction in
     * objectBoundingBox units.
     *
     * @param value the value
     * @param type the type of the value
     * @param d the direction of the value
     * @param ctx the context used to resolve relative value
     */
    public static float svgToObjectBoundingBox(float value,
                                               short type,
                                               short d,
                                               Context ctx) {
        switch (type) {
        case SVGLength.SVG_LENGTHTYPE_NUMBER:
            // as is
            return value;
        case SVGLength.SVG_LENGTHTYPE_PERCENTAGE:
            // If a percentage value is used, it is converted to a
            // 'bounding box' space coordinate by division by 100
            return value / 100f;
        case SVGLength.SVG_LENGTHTYPE_PX:
        case SVGLength.SVG_LENGTHTYPE_MM:
        case SVGLength.SVG_LENGTHTYPE_CM:
        case SVGLength.SVG_LENGTHTYPE_IN:
        case SVGLength.SVG_LENGTHTYPE_PT:
        case SVGLength.SVG_LENGTHTYPE_PC:
        case SVGLength.SVG_LENGTHTYPE_EMS:
        case SVGLength.SVG_LENGTHTYPE_EXS:
            // <!> FIXME: resolve units in userSpace but consider them
            // in the objectBoundingBox coordinate system
            return svgToUserSpace(value, type, d, ctx);
        default:
            throw new IllegalArgumentException("Length has unknown type");
        }
    }

    /////////////////////////////////////////////////////////////////////////
    // SVG methods - userSpace
    /////////////////////////////////////////////////////////////////////////


    /**
     * Returns the specified coordinate with the specified direction
     * in user units.
     *
     * @param s the 'other' coordinate
     * @param attr the attribute name that represents the length
     * @param d the direction of the coordinate
     * @param ctx the context used to resolve relative value
     */
    public static float svgToUserSpace(String s,
                                       String attr,
                                       short d,
                                       Context ctx) throws ParseException {
        LengthParser lengthParser = new LengthParser();
        UnitResolver ur = new UnitResolver();
        lengthParser.setLengthHandler(ur);
        lengthParser.parse(s);
        return svgToUserSpace(ur.value, ur.unit, d, ctx);
    }

    /**
     * Converts the specified value of the specified type and
     * direction to user units.
     *
     * @param v the value to convert
     * @param type the type of the value
     * @param d HORIZONTAL_LENGTH, VERTICAL_LENGTH, or OTHER_LENGTH
     * @param ctx the context used to resolve relative value
     */
    public static float svgToUserSpace(float v,
                                       short type,
                                       short d,
                                       Context ctx) {
        switch (type) {
        case SVGLength.SVG_LENGTHTYPE_NUMBER:
        case SVGLength.SVG_LENGTHTYPE_PX:
            return v;
        case SVGLength.SVG_LENGTHTYPE_MM:
            return (v / ctx.getPixelUnitToMillimeter());
        case SVGLength.SVG_LENGTHTYPE_CM:
            return (v * 10f / ctx.getPixelUnitToMillimeter());
        case SVGLength.SVG_LENGTHTYPE_IN:
            return (v * 25.4f / ctx.getPixelUnitToMillimeter());
        case SVGLength.SVG_LENGTHTYPE_PT:
            return (v * 25.4f / (72f * ctx.getPixelUnitToMillimeter()));
        case SVGLength.SVG_LENGTHTYPE_PC:
            return (v * 25.4f / (6f * ctx.getPixelUnitToMillimeter()));
        case SVGLength.SVG_LENGTHTYPE_EMS:
            return emsToPixels(v, d, ctx);
        case SVGLength.SVG_LENGTHTYPE_EXS:
            return exsToPixels(v, d, ctx);
        case SVGLength.SVG_LENGTHTYPE_PERCENTAGE:
            return percentagesToPixels(v, d, ctx);
        default:
            throw new IllegalArgumentException("Length has unknown type");
        }
    }

    /**
     * Converts the specified value of the specified type and
     * direction to SVG units.
     *
     * @param v the value to convert
     * @param type the type of the value
     * @param d HORIZONTAL_LENGTH, VERTICAL_LENGTH, or OTHER_LENGTH
     * @param ctx the context used to resolve relative value
     */
    public static float userSpaceToSVG(float v,
                                       short type,
                                       short d,
                                       Context ctx) {
        switch (type) {
        case SVGLength.SVG_LENGTHTYPE_NUMBER:
        case SVGLength.SVG_LENGTHTYPE_PX:
            return v;
        case SVGLength.SVG_LENGTHTYPE_MM:
            return (v * ctx.getPixelUnitToMillimeter());
        case SVGLength.SVG_LENGTHTYPE_CM:
            return (v * ctx.getPixelUnitToMillimeter() / 10f);
        case SVGLength.SVG_LENGTHTYPE_IN:
            return (v * ctx.getPixelUnitToMillimeter() / 25.4f);
        case SVGLength.SVG_LENGTHTYPE_PT:
            return (v * (72f * ctx.getPixelUnitToMillimeter()) / 25.4f);
        case SVGLength.SVG_LENGTHTYPE_PC:
            return (v * (6f * ctx.getPixelUnitToMillimeter()) / 25.4f);
        case SVGLength.SVG_LENGTHTYPE_EMS:
            return pixelsToEms(v, d, ctx);
        case SVGLength.SVG_LENGTHTYPE_EXS:
            return pixelsToExs(v, d, ctx);
        case SVGLength.SVG_LENGTHTYPE_PERCENTAGE:
            return pixelsToPercentages(v, d, ctx);
        default:
            throw new IllegalArgumentException("Length has unknown type");
        }
    }

    /////////////////////////////////////////////////////////////////////////
    // Utilities methods for relative length
    /////////////////////////////////////////////////////////////////////////

    /**
     * Converts percentages to user units.
     *
     * @param v the percentage to convert
     * @param d HORIZONTAL_LENGTH, VERTICAL_LENGTH, or OTHER_LENGTH
     * @param ctx the context
     */
    protected static float percentagesToPixels(float v, short d, Context ctx) {
        if (d == HORIZONTAL_LENGTH) {
            float w = ctx.getViewportWidth();
            return w * v / 100f;
        } else if (d == VERTICAL_LENGTH) {
            float h = ctx.getViewportHeight();
            return h * v / 100f;
        } else {
            double w = ctx.getViewportWidth();
            double h = ctx.getViewportHeight();
            double vpp = Math.sqrt(w * w + h * h) / SQRT2;
            return (float)(vpp * v / 100d);
        }
    }

    /**
     * Converts user units to percentages relative to the viewport.
     *
     * @param v the value to convert
     * @param d HORIZONTAL_LENGTH, VERTICAL_LENGTH, or OTHER_LENGTH
     * @param ctx the context
     */
    protected static float pixelsToPercentages(float v, short d, Context ctx) {
        if (d == HORIZONTAL_LENGTH) {
            float w = ctx.getViewportWidth();
            return v * 100f / w;
        } else if (d == VERTICAL_LENGTH) {
            float h = ctx.getViewportHeight();
            return v * 100f / h;
        } else {
            double w = ctx.getViewportWidth();
            double h = ctx.getViewportHeight();
            double vpp = Math.sqrt(w * w + h * h) / SQRT2;
            return (float)(v * 100d / vpp);
        }
    }

    /**
     * Converts user units to ems units.
     *
     * @param v the value to convert
     * @param d HORIZONTAL_LENGTH, VERTICAL_LENGTH, or OTHER_LENGTH
     * @param ctx the context
     */
    protected static float pixelsToEms(float v, short d, Context ctx) {
        return v / ctx.getFontSize();
    }

    /**
     * Converts ems units to user units.
     *
     * @param v the value to convert
     * @param d HORIZONTAL_LENGTH, VERTICAL_LENGTH, or OTHER_LENGTH
     * @param ctx the context
     */
    protected static float emsToPixels(float v, short d, Context ctx) {
        return v * ctx.getFontSize();
    }

    /**
     * Converts user units to exs units.
     *
     * @param v the value to convert
     * @param d HORIZONTAL_LENGTH, VERTICAL_LENGTH, or OTHER_LENGTH
     * @param ctx the context
     */
    protected static float pixelsToExs(float v, short d, Context ctx) {
        float xh = ctx.getXHeight();
        return v / xh / ctx.getFontSize();
    }

    /**
     * Converts exs units to user units.
     *
     * @param v the value to convert
     * @param d HORIZONTAL_LENGTH, VERTICAL_LENGTH, or OTHER_LENGTH
     * @param ctx the context
     */
    protected static float exsToPixels(float v, short d, Context ctx) {
        float xh = ctx.getXHeight();
        return v * xh * ctx.getFontSize();
    }


    /**
     * A LengthHandler that convert units.
     */
    public static class UnitResolver implements LengthHandler {

        /**
         * The length value.
         */
        public float value;

        /**
         * The length type.
         */
        public short unit = SVGLength.SVG_LENGTHTYPE_NUMBER;

        /**
         * Implements {@link LengthHandler#startLength()}.
         */
        public void startLength() throws ParseException {
        }

        /**
         * Implements {@link LengthHandler#lengthValue(float)}.
         */
        public void lengthValue(float v) throws ParseException {
            this.value = v;
        }

        /**
         * Implements {@link LengthHandler#em()}.
         */
        public void em() throws ParseException {
            this.unit = SVGLength.SVG_LENGTHTYPE_EMS;
        }

        /**
         * Implements {@link LengthHandler#ex()}.
         */
        public void ex() throws ParseException {
            this.unit = SVGLength.SVG_LENGTHTYPE_EXS;
        }

        /**
         * Implements {@link LengthHandler#in()}.
         */
        public void in() throws ParseException {
            this.unit = SVGLength.SVG_LENGTHTYPE_IN;
        }

        /**
         * Implements {@link LengthHandler#cm()}.
         */
        public void cm() throws ParseException {
            this.unit = SVGLength.SVG_LENGTHTYPE_CM;
        }

        /**
         * Implements {@link LengthHandler#mm()}.
         */
        public void mm() throws ParseException {
            this.unit = SVGLength.SVG_LENGTHTYPE_MM;
        }

        /**
         * Implements {@link LengthHandler#pc()}.
         */
        public void pc() throws ParseException {
            this.unit = SVGLength.SVG_LENGTHTYPE_PC;
        }

        /**
         * Implements {@link LengthHandler#pt()}.
         */
        public void pt() throws ParseException {
            this.unit = SVGLength.SVG_LENGTHTYPE_PT;
        }

        /**
         * Implements {@link LengthHandler#px()}.
         */
        public void px() throws ParseException {
            this.unit = SVGLength.SVG_LENGTHTYPE_PX;
        }

        /**
         * Implements {@link LengthHandler#percentage()}.
         */
        public void percentage() throws ParseException {
            this.unit = SVGLength.SVG_LENGTHTYPE_PERCENTAGE;
        }

        /**
         * Implements {@link LengthHandler#endLength()}.
         */
        public void endLength() throws ParseException {
        }
    }

    /**
     * Holds the informations needed to compute the units.
     */
    public interface Context {

        /**
         * Returns the element.
         */
        Element getElement();

        /**
         * Returns the size of a px CSS unit in millimeters.
         */
        float getPixelUnitToMillimeter();

        /**
         * Returns the size of a px CSS unit in millimeters.
         * This will be removed after next release.
         * @see #getPixelUnitToMillimeter()
         */
        float getPixelToMM();

        /**
         * Returns the font-size value.
         */
        float getFontSize();

        /**
         * Returns the x-height value.
         */
        float getXHeight();

        /**
         * Returns the viewport width used to compute units.
         */
        float getViewportWidth();

        /**
         * Returns the viewport height used to compute units.
         */
        float getViewportHeight();
    }
}
