#=

Base.convert() methods to convert shapefile geometry to Luxor geometry.

Use `include()` to include this file if you've installed Shapefile.jl.

Luxor y coordinates increase downwards, but maps and shapefile coordinates increase upwards.
In the Northern hemisphere, 0 longitude is North Pole, so we negate y coordinates.

```julia
using Luxor, Shapefile
worldshapefile = "TM_WORLD_BORDERS-0.3/TM_WORLD_BORDERS-0.3.shp"
include(splitdir(pathof(Luxor))[1] * "/readshapefiles.jl")
table = Shapefile.Table(worldshapefile)
geoms = Shapefile.shapes(table)
# set up Luxor drawing, then:
for shape in geoms
    pgons, bbox = convert(Vector{Luxor.Point}, shape)
    for pg in pgons
        setgray(rand(0.5:0.1:0.8))
        poly(pg, :fill)
    end
end
# tidy up
```

=#

# Convert a Shapefile rectangle to an array of points suitable for a Luxor rectangle
function Base.convert(::Type{Vector{Luxor.Point}}, R::Shapefile.Rect)
    return [R.left, R.top, R.right-R.left, R.bottom-R.top]
end

# Convert a Shapefile Point to a Luxor Point (flipping y-coordinates)
function  Base.convert(::Type{Luxor.Point}, pt::Shapefile.Point)
    return Luxor.Point(pt.x, -pt.y)
end

# Convert Shapefile PolyLine to a Luxor poly
function Base.convert(::Type{Vector{Luxor.Point}}, pl::Shapefile.Polyline)
    resultbbox = convert(Vector{Luxor.Point}, pl.MBR)
    resultpoly = Luxor.Point[]
    for pt in pl.points
        push!(resultpoly, convert(Luxor.Point, pt))
    end
    return resultbbox, resultpoly
end

# Convert Shapefile Polygon to a Luxor poly.
# some Shapefile polygons have multiple parts, but these aren't subpaths, just
# extra polygons. For example, France (in Europe) and French Guiana in (South America)
# belong to the same Shapefile.Polygon and the return value will include these and other
# polygons in the array.

function Base.convert(::Type{Vector{Luxor.Point}}, pl::Shapefile.Polygon)
    bbox = [Luxor.Point(pl.MBR.left, -pl.MBR.top), pl.MBR.right - pl.MBR.left, pl.MBR.top - pl.MBR.bottom]
    polygons = Vector{Point}[] # to hold all the polygons for a shape
    if length(pl.parts) >= 2
        points = Luxor.Point[]
        for i in 1:length(pl.parts) - 1
            subpolygonpoints = pl.points[pl.parts[i]+1: pl.parts[i + 1]]
            for pt in subpolygonpoints
                push!(points, convert(Luxor.Point, pt))
            end
            push!(polygons, points)
            points = Luxor.Point[]
        end
        # don't forget the rest
        subpolygonpoints = pl.points[pl.parts[end] + 1: end]
        for pt in subpolygonpoints
            push!(points, convert(Luxor.Point, pt))
        end
        push!(polygons, points)
    else
        points = Luxor.Point[]
        for pt in pl.points
            push!(points, convert(Luxor.Point, pt))
        end
        push!(polygons, points)
    end
    return polygons, bbox
end
