# 
# Copyright (c) 1991-2023 by STEP Tools Inc.
# All Rights Reserved
# 
# This software is furnished under a license and may be used and
# copied only in accordance with the terms of such license and with
# the inclusion of the above copyright notice.  This software and
# accompanying written materials or any other copies thereof may
# not be provided or otherwise made available to any other person.
# No title to or ownership of the software is hereby transferred.
# 
# Author: David Loffredo (loffredo@steptools.com)
# 

# format step date and time objects into ISO 8601 format

import math
import datetime
from steptools import step


def asdate(o:step.Object) -> datetime.date:
    # unwrap date from other object
    if o is None: return None
    if step.isinstance(o, 'date_and_time'):
        o = o.date_component
    elif step.isinstance(o, 'date_assignment'):
        o = o.assigned_date
    
    if step.isinstance(o, 'calendar_date'):
        return datetime.date(
            o.year_component,
            o.month_component,
            o.day_component
        )

    elif step.isinstance(o, 'year_month'):
        return datetime.date(
            o.year_component,
            o.month_component
        )

    elif step.isinstance(o, 'ordinal_date'):
        # we have code for this in roselib, but python does not
        ORD = datetime.date(o.year_component).toordinal - 1 + o.day_component
        ORDDT = datetime.date.fromordinal(ORD)
        D.month = ORDDT.month
        D.day = ORDDT.day
        
    elif step.isinstance(o, 'week_of_year_and_day_date'):
        return datetime.date.fromisocalendar(
            o.year_component,
            o.week_component,
            o.day_component
        )

    return None


def astime(o:step.Object) -> datetime.time:
    # unwrap time from other object
    if o is None: return None
    if step.isinstance(o, 'date_and_time'):
        o = o.time_component

    if step.isinstance(o, 'local_time'):
        TZ = None
        if o.zone is not None:
            TZH = o.zone.hour_offset
            TZM = o.zone.minute_offset
            if o.zone.sense == "BEHIND":
                TZH = - TZH
                if TZM is not None: TZM = -TZM
                
            TZ = datetime.timezone(datetime.timedelta(hours=TZH, minutes=TZM))

        return datetime.time(
            o.hour_component,
            o.minute_component,
            math.floor(o.second_component),
            tzinfo=TZ
        )

    return None


def asdatetime(o:step.Object) -> datetime.datetime:
    '''Return datetime from step date or time object'''
    if o is None: return None
    D = asdate(o)
    T = astime(o)

    if D is None and T is None:
        return None

    if D is None:
        return T.isoformat()

    if T is None:
        T = datetime.time()
        
    return datetime.datetime.combine(D, T)


def asisoformat(o:step.Object) -> str:
    '''Return ISO 8601 from step date or time object'''
    DT = asdatetime(o)
    if DT is not None:
        return DT.isoformat()

    return None


    

