/*
 * Copyright 2015-2024 MicroEJ Corp. All rights reserved.
 * This library is provided in source code for use, modification and test, subject to license terms.
 * Any modification of the source code will break MicroEJ Corp. warranties on the whole library.
 */
package ej.mwt.style.outline;

import ej.annotation.Nullable;
import ej.bon.XMath;
import ej.microui.display.GraphicsContext;
import ej.mwt.util.Outlineable;
import ej.mwt.util.Size;

/**
 * Flexible outline that has a different thickness for each edge.
 * <p>
 * The thicknesses are stored as a <code>char</code> for heap optimization and therefore cannot exceed
 * <code>65535</code>.
 */
public class FlexibleOutline implements Outline {

    /**
     * Creates a flexible outline specifying its thickness for each edge.
     * <p>
     * The given thickness values are clamped between <code>0</code> and <code>Character.MAX_VALUE</code>.
     *
     * @param top
     *            the top thickness.
     * @param right
     *            the right thickness.
     * @param bottom
     *            the bottom thickness.
     * @param left
     *            the left thickness.
     */
    public FlexibleOutline(int top, int right, int bottom, int left) {
        this.top = (char) XMath.limit(top, 0, Character.MAX_VALUE);
        this.right = (char) XMath.limit(right, 0, Character.MAX_VALUE);
        this.bottom = (char) XMath.limit(bottom, 0, Character.MAX_VALUE);
        this.left = (char) XMath.limit(left, 0, Character.MAX_VALUE);
    }

    /**
     * Gets the top thickness.
     *
     * @return the top thickness.
     */
    public int getTop() {
        return this.top;
    }

    /**
     * Gets the bottom thickness.
     *
     * @return the bottom thickness.
     */
    public int getBottom() {
        return this.bottom;
    }

    /**
     * Gets the left thickness.
     *
     * @return the left thickness.
     */
    public int getLeft() {
        return this.left;
    }

    /**
     * Gets the right thickness.
     *
     * @return the right thickness.
     */
    public int getRight() {
        return this.right;
    }

    @Override
    public void apply(Outlineable outlineable) {
        outlineable.removeOutline(this.left, this.top, this.right, this.bottom);
    }

    @Override
    public void apply(GraphicsContext g, Size size) {
        size.removeOutline(this.left, this.top, this.right, this.bottom);
        g.translate(this.left, this.top);
        g.intersectClip(0, 0, size.getWidth(), size.getHeight());
    }

    @Override
    public boolean equals(@Nullable Object obj) {
        if (obj != null && getClass() == obj.getClass()) {
            FlexibleOutline outline = (FlexibleOutline) obj;
            return this.top == outline.top && this.bottom == outline.bottom && this.left == outline.left && this.right == outline.right;
        }
        return false;
    }

    @Override
    public int hashCode() {
        return this.top * this.bottom * this.left * this.right;
    }
}
