export text, vline, hline, box, colorbar

# NOTE objects don't have the overwrite property. so with or witout ! they don't
# overwrite the axes they get placed on.

"""
    text(text, anchor)

### Example

    text((1, 1.5), t"x^{\\star}"; fontsize=15)
"""
function text(
            anchor::T2R;
            text::String,
            axes::Option{Axes}=nothing,
            o...
        )::PreviewFigure

    axes = check_axes(axes)
    # create object
    t = Text2D(;
            anchor = Float64.(anchor),
            text
    )
    set_properties!(t; o...)
    # add to axes
    push!(axes.objects, t)
    return PreviewFigure(gcf())
end


"""
    _line(...)

Internal function to draw a horizontal or vertical line from axis to axis.
See `vline` and `hline`.
"""
function _line(
            anchor::Float64,
            horiz::Bool;
            axes=nothing,
            o...
        )::PreviewFigure

    axes = check_axes(axes)
    # create object
    l = StraightLine2D(;
            anchor,
            horiz
    )
    set_properties!(l; o...)
    # add to axes
    push!(axes.objects, l)
    return PreviewFigure(gcf())
end


"""
    vline(anchor; opts...)

Add a vertical line at a given point from the xaxis to the x2axis.
Note that this does not adapt the xaxis limits so if the point specified is
outside of the current xaxis limits you won't see anything (until you adjust
the limits accordingly).
See also `hline`.

### Example

    vline(0; color="red")
"""
vline(anchor::Real; o...) = _line(Float64(anchor), false; o...)

"""
    hline(anchor; opts...)

Add a horizontal line at a given point from the yaxis to the y2axis.
See also `vline`.

### Example

    hline(0; color="red")

"""
hline(anchor::Real; o...) = _line(Float64(anchor), true; o...)


"""
    line(from, to; options)

Add a line from `from` (in `(x, y)` format) to `to` (same format).

### Example

    line((0, 0), (1, 1); ls="--")

Will draw a dashed line from (x=0, y=0) to (x=1, y=1).
"""
line(a::T2R, b::T2R; o...) =
    plot!([a[1], b[1]], [a[2], b[2]]; o...)


"""
    box(anchor; opts...)

Add a box at position `anchor`.

### Example

    box((0, 0), (1, 1))

Will draw a box at anchor `(0, 0)` with width `1` and height `1`.
"""
function box(
            anchor::T2R,
            size::T2R;
            axes=nothing,
            o...
        )::PreviewFigure

    axes = check_axes(axes)
    b = Box2D(;
            anchor = Float64.(anchor),
            size   = Float64.(size)
    )
    set_properties!(b; o...)
    push!(axes.objects, b)
    return PreviewFigure(gcf())
end


"""
    colorbar(zmin, zmax, cmap; o...)

Add a colorbar on a side of the axes corresponding to the span `[zmin,zmax]` with a given colormap
`cmap` (vector of colors).
"""
function colorbar(
            zmin::Real,
            zmax::Real,
            cmap::Vector{Color};
            axes::Option{Axes}=nothing,
            o...
        )::PreviewFigure

    axes = check_axes(axes)
    # check if there is an existing colorbar, if so remove it (see later)
    mask = isa.(axes.objects, Colorbar)

    # Create object
    b = Colorbar(;
            zmin = Float64(zmin),
            zmax = Float64(zmax),
            cmap
    )
    # axes adjustment
    if b.position ∈ ("left","right")  # horizontal
        axes.scale = "0.8 auto"
    else
        axes.scale = "auto 0.8"
    end
    set_properties!(b; o...)

    if any(mask)
        axes.objects[findfirst(mask)] = b
    else
        push!(axes.objects, b)
    end
    return PreviewFigure(gcf())
end

"""
    colorbar(h; o...)

Adds a colorbar to a drawing handle generated by a heatmap.

### Example

    h = heatmap(randn(20, 20))
    colorbar(h)

"""
colorbar(dh::DrawingHandle{Heatmap}; o...) =
    colorbar(dh.drawing.zmin, dh.drawing.zmax, dh.drawing.cmap; o...)
