"""
basemap - Plot base maps and frames.
"""

from collections.abc import Sequence
from typing import Literal

from pygmt.alias import Alias, AliasSystem
from pygmt.clib import Session
from pygmt.helpers import build_arg_list, fmt_docstring, use_alias


@fmt_docstring
@use_alias(
    L="map_scale",
    F="box",
    Td="rose",
    Tm="compass",
    f="coltypes",
)
def basemap(
    self,
    projection: str | None = None,
    zsize: float | str | None = None,
    zscale: float | str | None = None,
    frame: str | Sequence[str] | bool = False,
    region: Sequence[float | str] | str | None = None,
    verbose: Literal["quiet", "error", "warning", "timing", "info", "compat", "debug"]
    | bool = False,
    panel: int | Sequence[int] | bool = False,
    transparency: float | None = None,
    perspective: float | Sequence[float] | str | bool = False,
    **kwargs,
):
    r"""
    Plot base maps and frames.

    Creates a basic or fancy basemap with axes, fill, and titles. Several
    map projections are available, and the user may specify separate
    tick-mark intervals for boundary annotation, ticking, and [optionally]
    gridlines. A simple map scale or directional rose may also be plotted.

    At least one of the parameters ``frame``, ``map_scale``, ``rose``, or
    ``compass`` must be specified if not in subplot mode.

    Full GMT docs at :gmt-docs:`basemap.html`.

    $aliases
       - B = frame
       - J = projection
       - Jz = zscale
       - JZ = zsize
       - R = region
       - V = verbose
       - c = panel
       - p = perspective
       - t = transparency

    Parameters
    ----------
    $projection
    zscale/zsize
        Set z-axis scaling or z-axis size.
    $region
        *Required if this is the first plot command.*
    $frame
    map_scale : str
        [**g**\|\ **j**\|\ **J**\|\ **n**\|\ **x**]\ *refpoint*\
        **+w**\ *length*.
        Draw a simple map scale centered on the reference point specified.
    box : bool or str
        [**+c**\ *clearances*][**+g**\ *fill*][**+i**\ [[*gap*/]\ *pen*]]\
        [**+p**\ [*pen*]][**+r**\ [*radius*]][**+s**\ [[*dx*/*dy*/][*shade*]]].
        If set to ``True``, draw a rectangular border around the
        map scale or rose. Alternatively, specify a different pen with
        **+p**\ *pen*. Add **+g**\ *fill* to fill the scale panel [Default is
        no fill]. Append **+c**\ *clearance* where *clearance* is either gap,
        xgap/ygap, or lgap/rgap/bgap/tgap where these items are uniform,
        separate x and y, or individual side spacings between scale and
        border. Append **+i** to draw a secondary, inner border as well.
        We use a uniform gap between borders of 2 points and the
        :gmt-term:`MAP_DEFAULTS_PEN` unless other values are specified. Append
        **+r** to draw rounded rectangular borders instead, with a 6-points
        corner radius. You can override this radius by appending another value.
        Finally, append **+s** to draw an offset background shaded region.
        Here, *dx/dy* indicates the shift relative to the foreground frame
        [Default is ``"4p/-4p"``] and shade sets the fill style to use for
        shading [Default is ``"gray50"``].
    rose : str
        Draw a map directional rose on the map at the location defined by
        the reference and anchor points.
    compass : str
        Draw a map magnetic rose on the map at the location defined by the
        reference and anchor points.
    $verbose
    $panel
    $coltypes
    $perspective
    $transparency
    """
    self._activate_figure()

    aliasdict = AliasSystem(
        Jz=Alias(zscale, name="zscale"),
        JZ=Alias(zsize, name="zsize"),
    ).add_common(
        B=frame,
        J=projection,
        R=region,
        V=verbose,
        c=panel,
        p=perspective,
        t=transparency,
    )
    aliasdict.merge(kwargs)

    with Session() as lib:
        lib.call_module(module="basemap", args=build_arg_list(aliasdict))
