# Path: alphaware/enums.py
# class FreqType(StrEnum):
#     EOD = 'D'
#     EOW = 'W'
#     EOM = 'M'
#     EOQ = 'Q'
#     EOSY = 'S'
#     EOY = 'Y'
# 
# Path: alphaware/utils/input_validation.py
# @expect_types(arg=(list, np.ndarray, pd.DataFrame, pd.Series))
# def ensure_pd_series(func, argname, arg):
#     if isinstance(arg, pd.Series):
#         return arg
#     elif isinstance(arg, pd.DataFrame):
#         return arg[arg.columns[0]]
#     else:
#         return pd.Series(arg)
# 
# @expect_types(date=(str, datetime, Date))
# def ensure_pyfin_date(date, date_format='%Y-%m-%d'):
#     """
#     :param date: str, datetime, 日期
#     :param date_format: str, 时间格式
#     :return: PyFin.Date object 
#     """
#     if isinstance(date, Date):
#         return date
#     elif isinstance(date, str):
#         return Date.strptime(date, date_format)
#     else:
#         return Date.fromDateTime(date)


from datetime import datetime
from xutils.date_utils import (Calendar,
                               Date,
                               Period,
                               Schedule)
from xutils.date_utils import (BizDayConventions,
                               Weekdays)
from argcheck import (expect_types,
                      preprocess)
from alphaware.enums import FreqType
from .input_validation import (ensure_pd_series,
                               ensure_pyfin_date)
def map_to_biz_day(date_series, calendar='China.SSE', convention=BizDayConventions.Preceding):
    """
    :param date_series: array-like of datetime.datetime
    :param calendar: str, optional, 日历名称，见PyFin.DateUtilities.Calendar, default='China.SSE'
    :param convention: str, optional, 如果日期为节假日，如何调整成交易日，见PyFin.DateUtilities.Schedule, default = preceding
    :return: pd.Series, datetime.datetime， 交易日列表
    """
    unique_date_list = sorted(set(date_series))
    py_date_list = [Date.fromDateTime(date) for date in unique_date_list]
    py_date_list = [Calendar(calendar).adjustDate(date, convention) for date in py_date_list]
    biz_day_list = [Date.toDateTime(date) for date in py_date_list]
    dict_date_map = dict(zip(unique_date_list, biz_day_list))
    ret = date_series.map(dict_date_map)
    return ret


@expect_types(start_date=(str, datetime), end_date=(str, datetime), freq=(str, FreqType))
def get_tiaocang_date(start_date, end_date, freq=FreqType.EOM, calendar='China.SSE', date_format='%Y-%m-%d'):
    """
    :param start_date: str/datetime.datetime, 开始日期
    :param end_date: str/datetime.datetime, 结束日期
    :param freq: str enum, default=EOM, 月度
    :param calendar: str, 日历名称
    :param date_format: str, start_date/end_date 如果是str格式，其格式的日期形式
    :return: list, datetime.datetime
    返回在开始日至结束日之间的调仓日(交易日)
    """
    calendar = calendar
    date_format = date_format
    start_date = ensure_pyfin_date(start_date, date_format)

# Path: alphaware/enums.py
# class FreqType(StrEnum):
#     EOD = 'D'
#     EOW = 'W'
#     EOM = 'M'
#     EOQ = 'Q'
#     EOSY = 'S'
#     EOY = 'Y'
# 
# Path: alphaware/utils/input_validation.py
# @expect_types(arg=(list, np.ndarray, pd.DataFrame, pd.Series))
# def ensure_pd_series(func, argname, arg):
#     if isinstance(arg, pd.Series):
#         return arg
#     elif isinstance(arg, pd.DataFrame):
#         return arg[arg.columns[0]]
#     else:
#         return pd.Series(arg)
# 
# @expect_types(date=(str, datetime, Date))
# def ensure_pyfin_date(date, date_format='%Y-%m-%d'):
#     """
#     :param date: str, datetime, 日期
#     :param date_format: str, 时间格式
#     :return: PyFin.Date object 
#     """
#     if isinstance(date, Date):
#         return date
#     elif isinstance(date, str):
#         return Date.strptime(date, date_format)
#     else:
#         return Date.fromDateTime(date)


# Path: alphaware/utils/date_utils.py
from datetime import datetime
from xutils.date_utils import (Calendar,
                               Date,
                               Period,
                               Schedule)
from xutils.date_utils import (BizDayConventions,
                               Weekdays)
from argcheck import (expect_types,
                      preprocess)
from alphaware.enums import FreqType
from .input_validation import (ensure_pd_series,
                               ensure_pyfin_date)

def map_to_biz_day(date_series, calendar='China.SSE', convention=BizDayConventions.Preceding):
    """
    :param date_series: array-like of datetime.datetime
    :param calendar: str, optional, 日历名称，见PyFin.DateUtilities.Calendar, default='China.SSE'
    :param convention: str, optional, 如果日期为节假日，如何调整成交易日，见PyFin.DateUtilities.Schedule, default = preceding
    :return: pd.Series, datetime.datetime， 交易日列表
    """
    unique_date_list = sorted(set(date_series))
    py_date_list = [Date.fromDateTime(date) for date in unique_date_list]
    py_date_list = [Calendar(calendar).adjustDate(date, convention) for date in py_date_list]
    biz_day_list = [Date.toDateTime(date) for date in py_date_list]
    dict_date_map = dict(zip(unique_date_list, biz_day_list))
    ret = date_series.map(dict_date_map)
    return ret


@expect_types(start_date=(str, datetime), end_date=(str, datetime), freq=(str, FreqType))
def get_tiaocang_date(start_date, end_date, freq=FreqType.EOM, calendar='China.SSE', date_format='%Y-%m-%d'):
    """
    :param start_date: str/datetime.datetime, 开始日期
    :param end_date: str/datetime.datetime, 结束日期
    :param freq: str enum, default=EOM, 月度
    :param calendar: str, 日历名称
    :param date_format: str, start_date/end_date 如果是str格式，其格式的日期形式
    :return: list, datetime.datetime
    返回在开始日至结束日之间的调仓日(交易日)
    """
    calendar = calendar
    date_format = date_format
    start_date = ensure_pyfin_date(start_date, date_format)

    end_date = ensure_pyfin_date(end_date, date_format)