# Fiona's date and time is founded on RFC 3339.
#
# OGR knows 3 time "zones": GMT, "local time", amd "unknown". Fiona, when
# writing will convert times with a timezone offset to GMT (Z) and otherwise
# will write times with the unknown zone.

import logging
import re

log = logging.getLogger("Fiona")


# Fiona's 'date', 'time', and 'datetime' types are sub types of 'str'.


class FionaDateType(str):
    """Dates without time."""


class FionaTimeType(str):
    """Times without dates."""


class FionaDateTimeType(str):
    """Dates and times."""


pattern_date = re.compile(r"(\d\d\d\d)(-)?(\d\d)(-)?(\d\d)")
pattern_time = re.compile(
    r"(\d\d)(:)?(\d\d)(:)?(\d\d)?(\.\d+)?(Z|([+-])?(\d\d)?(:)?(\d\d))?")
pattern_datetime = re.compile(
    r"(\d\d\d\d)(-)?(\d\d)(-)?(\d\d)(T)?(\d\d)(:)?(\d\d)(:)?(\d\d)?(\.\d+)?(Z|([+-])?(\d\d)?(:)?(\d\d))?")


class group_accessor(object):
    def __init__(self, m):
        self.match = m

    def group(self, i):
        try:
            return self.match.group(i) or 0
        except IndexError:
            return 0


def parse_time(text):
    """ Given a time, returns a datetime tuple

    Parameters
    ----------
    text: string to be parsed

    Returns
    -------
        (int, int , int, int, int, int, int, int):
            datetime tuple: (year, month, day, hour, minute, second, microsecond, utcoffset in minutes or None)

    """
    match = re.search(pattern_time, text)
    if match is None:
        raise ValueError("Time data '%s' does not match pattern" % text)
    g = group_accessor(match)
    log.debug("Match groups: %s", match.groups())

    if g.group(8) == '-':
        tz = -1.0 * (int(g.group(9)) * 60 + int(g.group(11)))
    elif g.group(8) == '+':
        tz = int(g.group(9)) * 60 + int(g.group(11))
    else:
        tz = None

    return (0, 0, 0,
            int(g.group(1)),
            int(g.group(3)),
            int(g.group(5)),
            int(1000000.0 * float(g.group(6))),
            tz
            )


def parse_date(text):
    """Given a date, returns a datetime tuple

    Parameters
    ----------
    text: string to be parsed

    Returns
    -------
        (int, int , int, int, int, int, int, int):
            datetime tuple: (year, month, day, hour, minute, second, microsecond, utcoffset in minutes or None)
    """
    match = re.search(pattern_date, text)
    if match is None:
        raise ValueError("Time data '%s' does not match pattern" % text)
    g = group_accessor(match)
    log.debug("Match groups: %s", match.groups())
    return (
        int(g.group(1)),
        int(g.group(3)),
        int(g.group(5)),
        0, 0, 0, 0, None)


def parse_datetime(text):
    """Given a datetime, returns a datetime tuple

    Parameters
    ----------
    text: string to be parsed

    Returns
    -------
        (int, int , int, int, int, int, int, int):
            datetime tuple: (year, month, day, hour, minute, second, microsecond, utcoffset in minutes or None)
    """
    match = re.search(pattern_datetime, text)
    if match is None:
        raise ValueError("Time data '%s' does not match pattern" % text)
    g = group_accessor(match)
    log.debug("Match groups: %s", match.groups())

    if g.group(14) == '-':
        tz = -1.0 * (int(g.group(15)) * 60 + int(g.group(17)))
    elif g.group(14) == '+':
        tz = int(g.group(15)) * 60 + int(g.group(17))
    else:
        tz = None

    return (
        int(g.group(1)),
        int(g.group(3)),
        int(g.group(5)),
        int(g.group(7)),
        int(g.group(9)),
        int(g.group(11)),
        int(1000000.0 * float(g.group(12))),
        tz)
