/*
 * 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.sis.style.se1;

import java.util.List;
import java.util.ArrayList;
import jakarta.xml.bind.annotation.XmlType;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlElements;
import jakarta.xml.bind.annotation.XmlRootElement;

// Specific to the main branch:
import org.apache.sis.filter.Expression;


/**
 * A "graphic symbol" with an inherent shape, color(s), and possibly size.
 * A "graphic" can be very informally defined as "a little picture"
 * and can be of either a raster or vector-graphic source type.
 *
 * <!-- Following list of authors contains credits to OGC GeoAPI 2 contributors. -->
 * @author  Johann Sorel (Geomatys)
 * @author  Chris Dillard (SYS Technologies)
 * @author  Martin Desruisseaux (Geomatys)
 *
 * @param <R>  the type of data to style, such as {@code Feature} or {@code Coverage}.
 */
@XmlType(name = "GraphicType", propOrder = {
    "graphicalSymbols",
    "opacity",
    "size",
    "rotation",
    "anchorPoint",
    "displacement"
})
@XmlRootElement(name = "Graphic")
public class Graphic<R> extends StyleElement<R> implements Translucent<R> {
    /**
     * List of external image files or marks that comprise this graphic.
     * All elements of the list must be instances of either {@link Mark} or {@link ExternalGraphic}.
     * If empty it is to be treated a single default mark.
     *
     * @see #graphicalSymbols()
     */
    @XmlElements({
        @XmlElement(name = "Mark", type = Mark.class),
        @XmlElement(name = "ExternalGraphic", type = ExternalGraphic.class)
    })
    private List<GraphicalSymbol<R>> graphicalSymbols;

    /**
     * Level of translucency as a floating point number, or {@code null} for the default value.
     *
     * @see #getOpacity()
     * @see #setOpacity(Expression)
     *
     * @todo Needs a JAXB adapter to {@code ParameterValueType}.
     */
    @XmlElement(name = "Opacity")
    protected Expression<R, ? extends Number> opacity;

    /**
     * Absolute size of the graphic as a floating point number, or {@code null} for the default value.
     *
     * @see #getSize()
     * @see #setSize(Expression)
     *
     * @todo Needs a JAXB adapter to {@code ParameterValueType}.
     */
    @XmlElement(name = "Size")
    protected Expression<R, ? extends Number> size;

    /**
     * Rotation angle of the graphic when it is drawn, or {@code null} for the default value.
     *
     * @see #getRotation()
     * @see #setRotation(Expression)
     *
     * @todo Needs a JAXB adapter to {@code ParameterValueType}.
     */
    @XmlElement(name = "Rotation")
    protected Expression<R, ? extends Number> rotation;

    /**
     * Location to use for anchoring the graphic to the geometry, or {@code null} for lazily constructed default.
     *
     * @see #getAnchorPoint()
     * @see #setAnchorPoint(AnchorPoint)
     */
    @XmlElement(name = "AnchorPoint")
    protected AnchorPoint<R> anchorPoint;

    /**
     * Displacement from the "hot-spot" point, or {@code null} for lazily constructed default.
     *
     * @see #getDisplacement()
     * @see #setDisplacement(Displacement)
     */
    @XmlElement(name = "Displacement")
    protected Displacement<R> displacement;

    /**
     * For JAXB unmarshalling only.
     */
    private Graphic() {
        // Thread-local factory will be used.
    }

    /**
     * Creates a graphic initialized to opaque default mark, default size and no rotation.
     *
     * @param  factory  the factory to use for creating expressions and child elements.
     */
    public Graphic(final StyleFactory<R> factory) {
        super(factory);
        graphicalSymbols = new ArrayList<>();
    }

    /**
     * Creates a shallow copy of the given object.
     * For a deep copy, see {@link #clone()} instead.
     *
     * @param  source  the object to copy.
     */
    public Graphic(final Graphic<R> source) {
        super(source);
        graphicalSymbols = new ArrayList<>(source.graphicalSymbols);
        opacity          = source.opacity;
        size             = source.size;
        rotation         = source.rotation;
        anchorPoint      = source.anchorPoint;
        displacement     = source.displacement;
    }

    /**
     * Returns the list of external image files or marks that comprise this graphic.
     * All elements of the list shall be instances of either {@link Mark} or {@link ExternalGraphic}.
     * The list may contain multiple external URLs and marks with the semantic that they all provide
     * the equivalent graphic in different {@linkplain GraphicalSymbol#getFormat() formats}.
     *
     * <p>If the list is empty, it is to be treated as a single default mark.
     * That default is a square with with a 50%-gray fill and a black outline,
     * with a size of 6 pixels, unless an explicit {@linkplain #getSize() size} is specified.</p>
     *
     * <p>The returned collection is <em>live</em>:
     * changes in that collection are reflected into this object, and conversely.</p>
     *
     * @return list of marks or external graphics, as a live collection.
     */
    @SuppressWarnings("ReturnOfCollectionOrArrayField")
    public List<GraphicalSymbol<R>> graphicalSymbols() {
        return graphicalSymbols;
    }

    /**
     * Indicates the level of translucency as a floating point number between 0 and 1 (inclusive).
     * A value of zero means completely transparent. A value of 1.0 means completely opaque.
     *
     * @return the level of translucency as a floating point number between 0 and 1 (inclusive).
     *
     * @see Fill#getOpacity()
     * @see Stroke#getOpacity()
     * @see RasterSymbolizer#getOpacity()
     */
    @Override
    public Expression<R, ? extends Number> getOpacity() {
        return defaultToOne(opacity);
    }

    /**
     * Sets the level of translucency as a floating point number between 0 and 1 (inclusive).
     * If this method is never invoked, then the default value is literal 1 (totally opaque).
     * That default value is standardized by OGC 05-077r4.
     *
     * @param  value  new level of translucency, or {@code null} for resetting the default value.
     */
    @Override
    public void setOpacity(final Expression<R, ? extends Number> value) {
        opacity = value;
    }

    /**
     * Returns the absolute size of the graphic as a floating point number.
     * If a size is specified, the height of the graphic will be scaled to
     * that size and the aspect ratio will be used for computing the width.
     * The unit of measurement is given by {@link Symbolizer#getUnitOfMeasure()}.
     * Value shall be positive.
     *
     * <h4>Default value</h4>
     * The default size of an image format is the inherent size of the image.
     * The default size of an image format without an inherent size is defined
     * to be 16 pixels in height and the corresponding aspect in width.
     * If no image or mark is specified, then the size of the default mark is 6 pixels.
     * That default value is standardized by OGC 05-077r4.
     *
     * @return absolute size of the graphic as a floating point number, or {@code null} for the default value.
     */
    public Expression<R, ? extends Number> getSize() {
        final var value = size;
        if (value == null && graphicalSymbols.isEmpty()) {
            return factory.six;
        }
        return value;
    }

    /**
     * Sets the absolute size of the graphic as a floating point number.
     * If this method is never invoked, then the default value is {@code null}.
     *
     * @param  value  new absolute size of the graphic, or {@code null} for the default value.
     */
    public void setSize(final Expression<R, ? extends Number> value) {
        size = value;
    }

    /**
     * Returns the rotation angle of the graphic when it is drawn.
     * The rotation is in the clockwise direction around the graphic center point in decimal degrees.
     * Negative values mean counter-clockwise rotation. The default value is 0.0 (no rotation).
     *
     * <p>The point within the graphic about which it is rotated is format dependent.
     * If a format does not include an inherent rotation point,
     * then the point of rotation should be the centroid.</p>
     *
     * @return the rotation angle of the graphic when it is drawn.
     */
    public Expression<R, ? extends Number> getRotation() {
        return defaultToZero(rotation);
    }

    /**
     * Sets the rotation angle of the graphic when it is drawn.
     * If this method is never invoked, then the default value is literal 0.
     *
     * @param  value  new rotation angle of the graphic, or {@code null} for resetting the default value.
     */
    public void setRotation(final Expression<R, ? extends Number> value) {
        rotation = value;
    }

    /**
     * Returns the location inside of a graphic to use for anchoring the graphic to the main-geometry point.
     * The coordinates are given as (<var>x</var>,<var>y</var>) floating-point numbers
     * relative the graphic bounding box, where (0,0) is the lower-left corner and
     * (1,1) is the upper-right corner.
     *
     * <p>The returned object is <em>live</em>:
     * changes in the returned instance will be reflected in this graphic, and conversely.</p>
     *
     * @return the anchor point.
     */
    public AnchorPoint<R> getAnchorPoint() {
        if (anchorPoint == null) {
            anchorPoint = factory.createAnchorPoint();
        }
        return anchorPoint;
    }

    /**
     * Sets the location inside of a graphic to use for anchoring the graphic to the main-geometry point.
     * The given instance is stored by reference, it is not cloned. If this method is never invoked,
     * then the default value is a {@linkplain AnchorPoint#AnchorPoint() default anchor point}.
     *
     * @param  value  new anchor point, or {@code null} for resetting the default value.
     */
    public void setAnchorPoint(final AnchorPoint<R> value) {
        anchorPoint = value;
    }

    /**
     * Returns the two-dimensional displacement from the "hot-spot" point.
     * This element may be used to avoid over-plotting of multiple graphic symbols for the same point.
     * The unit of measurement is given by {@link Symbolizer#getUnitOfMeasure()}.
     * Positive values are to the right of the point.
     * The default displacement is <var>x</var> = 0, <var>y</var> = 0,
     *
     * <p>If displacement is used in conjunction with size and/or rotation
     * then the graphic symbol shall be scaled and/or rotated before it is displaced.</p>
     *
     * @return displacement from the "hot-spot" point.
     *
     * @see PolygonSymbolizer#getDisplacement()
     * @see PointPlacement#getDisplacement()
     */
    public Displacement<R> getDisplacement() {
        if (displacement == null) {
            displacement = factory.createDisplacement();
        }
        return displacement;
    }

    /**
     * Sets the two-dimensional displacement from the "hot-spot" point.
     * The given instance is stored by reference, it is not cloned. If this method is never invoked,
     * then the default value is a {@linkplain Displacement#Displacement() default displacement}.
     *
     * @param  value  new displacement from the "hot-spot" point, or {@code null} for resetting the default value.
     */
    public void setDisplacement(final Displacement<R> value) {
        displacement = value;
    }

    /**
     * Returns all properties contained in this class.
     * This is used for {@link #equals(Object)} and {@link #hashCode()} implementations.
     */
    @Override
    final Object[] properties() {
        return new Object[] {graphicalSymbols, opacity, size, rotation, anchorPoint, displacement};
    }

    /**
     * Returns a deep clone of this object. All style elements are cloned,
     * but expressions are not on the assumption that they are immutable.
     *
     * @return deep clone of all style elements.
     */
    @Override
    public Graphic<R> clone() {
        final var clone = (Graphic<R>) super.clone();
        clone.selfClone();
        return clone;
    }

    /**
     * Clones the mutable style fields of this element.
     */
    private void selfClone() {
        graphicalSymbols = new ArrayList<>(graphicalSymbols);
        graphicalSymbols.replaceAll(GraphicalSymbol::clone);
        if (anchorPoint  != null) anchorPoint  = anchorPoint .clone();
        if (displacement != null) displacement = displacement.clone();
    }
}
