1from __future__ import absolute_import
2
3import re
4
5from gcalcli.exceptions import ValidationError
6from gcalcli.utils import REMINDER_REGEX, get_time_from_str
7from six.moves import input
8
9# TODO: in the future, pull these from the API
10# https://developers.google.com/calendar/v3/reference/colors
11VALID_OVERRIDE_COLORS = ['lavender', 'sage', 'grape', 'flamingo',
12                         'banana', 'tangerine', 'peacock', 'graphite',
13                         'blueberry', 'basil', 'tomato']
14
15
16def get_override_color_id(color):
17    return str(VALID_OVERRIDE_COLORS.index(color) + 1)
18
19
20def get_input(printer, prompt, validator_func):
21    printer.msg(prompt, 'magenta')
22    while True:
23        try:
24            output = validate_input(validator_func)
25            return output
26        except ValidationError as e:
27            printer.msg(e.message, 'red')
28            printer.msg(prompt, 'magenta')
29
30
31def color_validator(input_str):
32    """
33    A filter allowing only the particular colors used by the Google Calendar
34    API
35
36    Raises ValidationError otherwise.
37    """
38    try:
39        assert input_str in VALID_OVERRIDE_COLORS + ['']
40        return input_str
41    except AssertionError:
42        raise ValidationError(
43                'Expected colors are: ' +
44                ', '.join(color for color in VALID_OVERRIDE_COLORS) +
45                '. (Ctrl-C to exit)\n')
46
47
48def str_to_int_validator(input_str):
49    """
50    A filter allowing any string which can be
51    converted to an int.
52    Raises ValidationError otherwise.
53    """
54    try:
55        int(input_str)
56        return input_str
57    except ValueError:
58        raise ValidationError(
59            'Input here must be a number. (Ctrl-C to exit)\n'
60        )
61
62
63def parsable_date_validator(input_str):
64    """
65    A filter allowing any string which can be parsed
66    by dateutil.
67    Raises ValidationError otherwise.
68    """
69    try:
70        get_time_from_str(input_str)
71        return input_str
72    except ValueError:
73        raise ValidationError(
74            'Expected format: a date (e.g. 2019-01-01, tomorrow 10am, '
75            '2nd Jan, Jan 4th, etc) or valid time if today. '
76            '(Ctrl-C to exit)\n'
77        )
78
79
80def str_allow_empty_validator(input_str):
81    """
82    A simple filter that allows any string to pass.
83    Included for completeness and for future validation if required.
84    """
85    return input_str
86
87
88def non_blank_str_validator(input_str):
89    """
90    A simple filter allowing string len > 1 and not None
91    Raises ValidationError otherwise.
92    """
93    if input_str in [None, '']:
94        raise ValidationError(
95            'Input here cannot be empty. (Ctrl-C to exit)\n'
96        )
97    else:
98        return input_str
99
100
101def reminder_validator(input_str):
102    """
103    Allows a string that matches utils.REMINDER_REGEX.
104    Raises ValidationError otherwise.
105    """
106    match = re.match(REMINDER_REGEX, input_str)
107    if match or input_str == '.':
108        return input_str
109    else:
110        raise ValidationError('Expected format: <number><w|d|h|m> '
111                              '<popup|email|sms>. (Ctrl-C to exit)\n')
112
113
114def validate_input(validator_func):
115    """
116    Wrapper around Validator funcs.
117    """
118    inp_str = input()
119    return validator_func(inp_str)
120
121
122STR_NOT_EMPTY = non_blank_str_validator
123STR_ALLOW_EMPTY = str_allow_empty_validator
124STR_TO_INT = str_to_int_validator
125PARSABLE_DATE = parsable_date_validator
126VALID_COLORS = color_validator
127REMINDER = reminder_validator
128