import sys
from argparse import ArgumentParser, Namespace, RawTextHelpFormatter


from pbp import get_pbp_version
from pbp.hmb_gen.misc_helper import print_given_args
from os import getenv


def parse_arguments() -> Namespace:
    version = get_pbp_version()

    # Check if --version is in arguments to avoid showing header
    is_version_request = "--version" in sys.argv

    # Custom formatter to add version header before usage
    class CustomHelpFormatter(RawTextHelpFormatter):
        def format_help(self):
            help_text = super().format_help()
            # Only prepend version info if not showing version
            if not is_version_request:
                return f"mbari-pbp {version}\n\nhmb-gen: Process ocean audio data archives to daily analysis products of hybrid millidecade spectra using PyPAM.\n\n{help_text}"
            return help_text

    example = """
Examples:
    pbp hmb-gen --json-base-dir=tests/json \\
        --audio-base-dir=tests/wav \\
        --date=20220902 \\
        --output-dir=output
    """

    parser = ArgumentParser(
        description="",
        epilog=example,
        formatter_class=CustomHelpFormatter,
        prog="pbp hmb-gen",
    )

    parser.add_argument(
        "--version",
        action="version",
        version=version,
    )

    parser.add_argument(
        "--json-base-dir",
        type=str,
        metavar="dir",
        help="JSON base directory",
    )

    parser.add_argument(
        "--audio-base-dir",
        type=str,
        metavar="dir",
        default=None,
        help="Audio base directory. By default, none",
    )

    parser.add_argument(
        "--global-attrs",
        type=str,
        metavar="uri",
        default=None,
        help="URI of JSON file with global attributes to be added to the NetCDF file.",
    )

    parser.add_argument(
        "--set-global-attr",
        type=str,
        nargs=2,
        default=None,
        metavar=("key", "value"),
        dest="set_global_attrs",
        action="append",
        help="Replace {{key}} with the given value for every occurrence of {{key}}"
        " in the global attrs file.",
    )

    parser.add_argument(
        "--variable-attrs",
        type=str,
        metavar="uri",
        default=None,
        help="URI of JSON file with attributes to associate to the variables in the NetCDF file.",
    )

    parser.add_argument(
        "--audio-path-map-prefix",
        type=str,
        metavar="from~to",
        default="",
        help="Prefix mapping to get actual audio uri to be used."
        " Example: 's3://pacific-sound-256khz-2022~file:///PAM_Archive/2022'.",
    )

    parser.add_argument(
        "--audio-path-prefix",
        type=str,
        metavar="dir",
        default="",
        help="Ad hoc path prefix for sound file location, for example, /Volumes."
        " By default, no prefix applied.",
    )

    parser.add_argument(
        "--date",
        type=str,
        metavar="YYYYMMDD",
        help="The date to be processed.",
    )

    parser.add_argument(
        "--exclude-tone-calibration",
        type=int,
        default=None,
        metavar="seconds",
        help="Set the number of seconds to exclude from each input audio file."
        " See https://github.com/mbari-org/pbp/issues/82.",
    )

    parser.add_argument(
        "--voltage-multiplier",
        type=float,
        default=None,
        metavar="value",
        help="Applied on the loaded signal.",
    )

    parser.add_argument(
        "--sensitivity-uri",
        type=str,
        default=None,
        metavar="file",
        help="URI of sensitivity NetCDF for calibration of result. "
        "Has precedence over --sensitivity-flat-value.",
    )

    parser.add_argument(
        "--sensitivity-flat-value",
        type=float,
        default=None,
        metavar="value",
        help="Flat sensitivity value to be used for calibration.",
    )

    parser.add_argument(
        "--output-dir",
        type=str,
        metavar="dir",
        required=True,
        help="Output directory",
    )

    parser.add_argument(
        "--output-prefix",
        type=str,
        metavar="prefix",
        default="milli_psd_",
        help="Output filename prefix",
    )

    parser.add_argument(
        "--no-netcdf-compression",
        dest="compress_netcdf",
        default=True,
        action="store_false",
        help="Do not compress the generated NetCDF file.",
    )

    parser.add_argument(
        "--add-quality-flag",
        dest="add_quality_flag",
        default=False,
        action="store_true",
        help="Add quality flag variable (with value 2 - 'Not evaluated') to the generated NetCDF file.",
    )

    parser.add_argument(
        "--s3",
        default=False,
        action="store_true",
        help="s3 access is involved, possibly with required credentials.",
    )

    parser.add_argument(
        "--s3-unsigned",
        default=False,
        action="store_true",
        help="s3 access is involved, not requiring credentials.",
    )

    parser.add_argument(
        "--gs",
        default=False,
        action="store_true",
        help="gs access involved.",
    )

    parser.add_argument(
        "--download-dir",
        type=str,
        metavar="dir",
        default=None,
        help="Directory for any downloads (e.g., when s3 or gs is involved).",
    )

    parser.add_argument(
        "--assume-downloaded-files",
        default=False,
        action="store_true",
        help="If any destination file for a download exists, assume it was downloaded already.",
    )

    parser.add_argument(
        "--retain-downloaded-files",
        default=False,
        action="store_true",
        help="Do not remove any downloaded files after use.",
    )

    parser.add_argument(
        "--max-segments",
        type=int,
        default=0,
        metavar="num",
        help="Test convenience: limit number of segments to process. By default, 0 (no limit).",
    )

    parser.add_argument(
        "--subset-to",
        type=int,
        nargs=2,
        default=None,
        metavar=("lower", "upper"),
        help="Subset the resulting PSD to [lower, upper), in terms of central frequency.",
    )

    # https://github.com/mbari-org/pbp/issues/89
    parser.add_argument(
        "--input-file",
        type=str,
        metavar="file",
        help="Input file",
    )
    parser.add_argument(
        "--timestamp-pattern",
        type=str,
        metavar="file",
        help="Pattern to extract timestamp from input file name",
    )
    parser.add_argument(
        "--time-resolution",
        type=int,
        metavar="secs",
        help="Time resolution in seconds",
    )

    args = parser.parse_args()
    if getenv("PRINT_GIVEN_ARGS") is not None:
        print_given_args(parser, args)

    return args
