# ----------------------------------------------------------------------
# Copyright (c) 2024 Rafael Gonzalez.
#
# See the LICENSE file for details
# ----------------------------------------------------------------------

# --------------------
# System wide imports
# -------------------

import os

from argparse import ArgumentParser

# ---------------------------
# Third-party library imports
# ----------------------------

from lica.validators import vdir, vdate
from lica.asyncio.photometer import Model as PhotModel, Sensor
from zptessdao.constants import CentralTendency, Calibration


# --------------
# local imports
# -------------

from .validator import vendpoint


def bdir() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-b",
        "--base-dir",
        type=vdir,
        default=os.getcwd(),
        metavar="<Dir>",
        help="Base directory for CSV export (default %(default)s)",
    )
    return parser


def idir() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-i",
        "--input-dir",
        type=vdir,
        default=os.getcwd(),
        metavar="<Dir>",
        help="Input CSV directory (default %(default)s)",
    )
    return parser


def odir() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-o",
        "--output-dir",
        type=vdir,
        default=os.getcwd(),
        metavar="<Dir>",
        help="Output CSV directory (default %(default)s)",
    )
    return parser


def buf() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-b",
        "--buffer",
        type=int,
        default=None,
        help="Circular buffer size (default %(default)s)",
    )
    return parser


def info() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "--info",
        default=False,
        action="store_true",
        help="Query photometer info and exit (default %(default)s)",
    )
    return parser


def persist() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-p",
        "--persist",
        default=False,
        action="store_true",
        help="Store calibration results in database (default %(default)s)",
    )
    return parser


def author() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-a",
        "--author",
        nargs="+",
        default=None,
        help="Calibration author (default %(default)s)",
    )
    return parser


def upd() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-u",
        "--update",
        default=False,
        action="store_true",
        help="Update Zero Point in test photometer (default %(default)s)",
    )
    return parser


def wrzp() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-z",
        "--zero-point",
        type=float,
        metavar="<ZP>",
        required=True,
        help="Writed Zero Point to test photometer (default %(default)s)",
    )
    return parser


def nmsg() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-N",
        "--num-messages",
        type=int,
        metavar="<N>",
        default=None,
        help="Number of messages to receive (default %(default)s)",
    )
    return parser


def ref() -> ArgumentParser:
    """Reference parser options"""
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-rE",
        "--ref-endpoint",
        type=vendpoint,
        default=None,
        metavar="<ref endpoint>",
        help="Reference photometer endpoint",
    )
    parser.add_argument(
        "-rM",
        "--ref-model",
        type=PhotModel,
        default=None,
        choices=PhotModel,
        help="Ref. photometer model, defaults to %(default)s",
    )
    parser.add_argument(
        "-rO",
        "--ref-old-proto",
        action="store_true",
        default=False,
        help="Use very old protocol instead of JSON, defaults to %(default)s",
    )
    parser.add_argument(
        "-rS",
        "--ref-sensor",
        type=Sensor,
        default=None,
        choices=Sensor,
        help="Reference phot sensor, defaults to %(default)s",
    )
    parser.add_argument(
        "-rR",
        "--ref-raw-message",
        action="store_true",
        default=False,
        help="Log raw messages, defaults to %(default)s",
    )
    parser.add_argument(
        "-rT",
        "--ref-strict",
        action="store_true",
        default=False,
        help="Strict samples rejection by timestamp difference, defaults to %(default)s",
    )
    return parser


def test() -> ArgumentParser:
    """Test parser options"""
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-tE",
        "--test-endpoint",
        type=vendpoint,
        default=None,
        metavar="<test endpoint>",
        help="Test photometer endpoint",
    )
    parser.add_argument(
        "-tM",
        "--test-model",
        type=PhotModel,
        default=None,
        choices=PhotModel,
        help="Test photometer model, defaults to %(default)s",
    )
    parser.add_argument(
        "-tO",
        "--test-old-proto",
        action="store_true",
        default=None,
        help="Use very old protocol instead of JSON, defaults to %(default)s",
    )
    parser.add_argument(
        "-tS",
        "--test-sensor",
        type=Sensor,
        default=None,
        choices=Sensor,
        help="Test photometer sensor, defaults to %(default)s",
    )
    parser.add_argument(
        "-tR",
        "--test-raw-message",
        action="store_true",
        default=False,
        help="Log raw messages, defaults to %(default)s",
    )
    parser.add_argument(
        "-tT",
        "--test-strict",
        action="store_true",
        default=False,
        help="Strict samples rejection by timestamp difference, defaults to %(default)s",
    )
    return parser


def stats() -> ArgumentParser:
    """Statistics parser options"""
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-C",
        "--central",
        type=CentralTendency,
        default=None,
        choices=CentralTendency,
        help="central tendency estimator, defaults to %(default)s",
    )
    parser.add_argument(
        "-R",
        "--rounds",
        type=int,
        default=None,
        metavar="<N>",
        help="Number of calibration rounds, defaults to %(default)s",
    )
    parser.add_argument(
        "-P",
        "--period",
        type=float,
        default=None,
        metavar="<sec.>",
        help="Wait period between rounds[s], defaults to %(default)s",
    )
    parser.add_argument(
        "-Z",
        "--zp-fict",
        type=float,
        default=None,
        metavar="<float>",
        help="Alternative ficticious Zero Point to use for both photometers, defaults to %(default)s",
    )
    parser.add_argument(
        "-O",
        "--zp-offset",
        type=float,
        default=None,
        metavar="<float>",
        help="Offset to add to calibrated Zero Point, defaults to %(default)s",
    )
    return parser


def no_bat() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-n",
        "--no-batch",
        default=False,
        action="store_true",
        help="Persistent calibration without an open batch (default %(default)s)",
    )
    return parser


def sess() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-s",
        "--session",
        type=vdate,
        metavar="<YYYY-MM-DDTHH:MM:SS>",
        required=True,
        help="session identifier",
    )
    return parser


# ------------------------------
# These are for batch management
# ------------------------------


def comm() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-c",
        "--comment",
        type=str,
        nargs="+",
        default=None,
        help="Optional batch comment (default %(default)s)",
    )
    return parser


def tbl() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "--page-size",
        type=int,
        default=10,
        help="Table page size",
    )
    parser.add_argument(
        "--table-format",
        choices=("simple", "grid"),
        default="simple",
        help="List batches",
    )
    return parser


def lst() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "--list",
        action="store_true",
        help="List orphan summaries one by one",
    )
    return parser


def expor() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    ex1 = parser.add_mutually_exclusive_group(required=True)
    ex1.add_argument(
        "-b",
        "--begin-date",
        type=vdate,
        metavar="<YYYY-MM-DDTHH:MM:SS>",
        default=None,
        help="by begin date",
    )
    ex1.add_argument("-l", "--latest", action="store_true", help="latest closed batch")
    ex1.add_argument("-a", "--all", action="store_true", help="all closed batches")
    parser.add_argument("-d", "--base-dir", type=vdir, default=".", help="Base dir for the export")
    parser.add_argument("-e", "--email", action="store_true", help="Send results by email")
    parser.add_argument(
        "-u",
        "--updated",
        action="store_true",
        help="Do action only when ZP updated flag is True|False",
    )
    return parser


def trange() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-s",
        "--since",
        type=vdate,
        metavar="<YYYY-MM-DDTHH:MM:SS>",
        default=None,
        help="since date, defaults to beginning of current year",
    )
    parser.add_argument(
        "-u",
        "--until",
        type=vdate,
        metavar="<YYYY-MM-DDTHH:MM:SS>",
        default=None,
        help="until date, defaults to end of current year",
    )
    return parser


def detailed() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-d",
        "--detailed",
        action="store_true",
        help="Export a CSV with a summary (only) for a given time span",
    )
    return parser


def mode() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    parser.add_argument(
        "-m",
        "--mode",
        type=Calibration,
        default=None,
        choices=Calibration,
        help="Calibration mode, defaults to %(default)s",
    )
    return parser


def ploto() -> ArgumentParser:
    parser = ArgumentParser(add_help=False)
    ex1 = parser.add_mutually_exclusive_group(required=False)
    ex1.add_argument("-sa", "--plot-samples", action="store_true", help="Ref/test samples vs time")
    ex1.add_argument("-hi", "--plot-histo", action="store_true", help="Ref/Test samples histogram")
    ex1.add_argument("-bo", "--plot-both", action="store_true", help="Ref/Test hist + samples vs time")
    parser.add_argument(
        "-me",
        "--median",
        action="store_true",
        help="Stats use median instead of mean",
    )
    return parser
