class ClassApiMixin:
    class_default_props = ['cls_id', 'cls_name', 'com_id']
    class_props = ['cls_change_ex', 'cls_def_pw_account', 'cls_def_pw_console', 'cls_def_pw_enable',
                   'cls_email_logs', 'cls_end_date', 'cls_id', 'cls_lab_limit', 'cls_max_slots_per_res',
                   'cls_min_hours_btw_res', 'cls_name', 'cls_no_delete', 'cls_retain_ilt', 'cls_retain_period',
                   'cls_retain_st', 'cls_self_sched', 'cls_start_date', 'cls_team_sched', 'cls_uuid', 'com_id',
                   'enrollment', 'leads']

    roster_default_props = ['acc_id', 'acc_user_id', 'acc_email', 'lead']
    roster_props = ['acc_display_name', 'acc_email', 'acc_full_name', 'acc_id', 'acc_last_login', 'acc_logins',
                    'acc_sort_name', 'acc_time_last_access', 'acc_type', 'acc_user_id', 'cls_id', 'lead', 'ros_team']

    def class_list(self, *, com_id=None, member=False, properties="default", **kwargs):
        """
        This method allows you to retrieve a list of classes and their properties.

        :param str com_id: Community ID.
        :param bool member: If true, get list of classes the caller is in.
        :param properties: List of properties to retrieve. See Returns section for list of available properties.
        :type properties: str or list

        :return: On success, returns an object with the requested properties:
        :rtype: dict

        **Properties**

        cls_change_ex
            Allow student to change exercise.
        cls_def_pw_account
            Class default account password.
        cls_def_pw_console
            Class default console password.
        cls_def_pw_enable
            Class default enable password.
        cls_email_logs
            Email reservation logs for real equipment pods. (N=No, P=Email primary instructor)
        cls_end_date
            Class end date.
        cls_id
            Unique class identifier.
        cls_lab_limit
            Lab limit settings. (E=Enforce class lab limit, I=Instructor override)
        cls_max_slots_per_res
            Maximum number of slots per reservation.
        cls_min_hours_btw_res
            Minimum number of hours between reservations.
        cls_name
            Unique class name per community.
        cls_no_delete
            Prevent from deletion.
        cls_retain_ilt
            Retain instructor led logs.
        cls_retain_period
            Number of days to retain class logs.
        cls_retain_st
            Retain student logs.
        cls_self_sched
            Allow students to self schedule.
        cls_start_date
            Class start date.
        cls_team_sched
            Allow teams to schedule.
        cls_uuid
            Class UUID.
        com_id
            Unique community identifier.
        enrollment
            Count of those enrolled.
        leads
            List of leads and properties sorted by acc_sort_name.
        """
        method = "class.list"
        if properties == 'all':
            properties = self.class_props
        if properties == 'default':
            properties = self.class_default_props
        return self.call(method, com_id=com_id, member=member, properties=properties, **kwargs)

    def class_add(self, *, cls_name, com_id, cls_change_ex=True, cls_def_pw_account=None, cls_def_pw_console=None,
                  cls_def_pw_enable=None, cls_email_logs="N", cls_end_date=None, cls_lab_limit="E",
                  cls_max_slots_per_res=None, cls_min_hours_btw_res=None, cls_no_delete=False, cls_retain_ilt=False,
                  cls_retain_period=None, cls_retain_st=True, cls_self_sched=True, cls_start_date=None,
                  cls_team_sched=False, **kwargs):
        """
        This method allows you to add a class to the NETLAB+ system.

        :param str cls_name: Class name.
        :param int com_id: Community ID.

        :param bool cls_change_ex: Allow student to change exercise.
        :param str cls_def_pw_account: Class default account password.
        :param str cls_def_pw_console: Class default console password.
        :param str cls_def_pw_enable: Class default enable password.
        :param str cls_email_logs: Email reservation logs for real equipment pods:
            'N' - Don't email logs 'P' - Email to primary instructor
        :param datetime.date cls_end_date: Class end date.
        :param str cls_lab_limit: Class lab time limit:
            'E' - Enforce time limit or 'I' - Ignore time limit.
        :param int cls_max_slots_per_res: Maximum number of slots per reservation.
        :param int cls_min_hours_btw_res: Minimum hours between reservations.
        :param bool cls_no_delete: Prevent from deletion.
        :param bool cls_retain_ilt: Retain instructor led logs.
        :param int cls_retain_period: The number of days to retain logs for.
        :param bool cls_retain_st: Retain student logs.
        :param bool cls_self_sched: Allow students to self schedule.
        :param datetime.date cls_start_date: Class start date.
        :param bool cls_team_sched: Allow teams to schedule.

        :return: On success, returns the Class ID of the newly created class.
        :rtype cls_id: int
        """

        method = "class.add"
        params = {'cls_name': cls_name, 'com_id': com_id, 'cls_change_ex': cls_change_ex,
                  'cls_email_logs': cls_email_logs.upper(), 'cls_lab_limit': cls_lab_limit.upper(),
                  'cls_no_delete': cls_no_delete, 'cls_retain_ilt': cls_retain_ilt, 'cls_retain_st': cls_retain_st,
                  'cls_self_sched': cls_self_sched, 'cls_team_sched': cls_team_sched}

        if cls_def_pw_account:
            params['cls_def_pw_account'] = cls_def_pw_account
        if cls_def_pw_console:
            params['cls_def_pw_console'] = cls_def_pw_console
        if cls_def_pw_enable:
            params['cls_def_pw_enable'] = cls_def_pw_enable

        if cls_start_date:
            params['cls_start_date'] = cls_start_date
        if cls_end_date:
            params['cls_end_date'] = cls_end_date

        if cls_max_slots_per_res:
            params['cls_max_slots_per_res'] = cls_max_slots_per_res
        if cls_min_hours_btw_res:
            params['cls_min_hours_btw_res'] = cls_min_hours_btw_res

        if cls_retain_period:
            params['cls_retain_period'] = cls_retain_period

        params.update(kwargs)
        return int(self.call(method, **params))

    def class_get(self, *, cls_id, properties="default", **kwargs):
        """
        This method allows you to retrieve a single class and properties.

        :param str cls_id: Class ID.
        :type cls_id: str
        :param properties: List of properties to retrieve. Defaults to "all"
        :type properties: str or list
        :return: On success, returns an object with the requested properties:
        :rtype: dict

        **Properties**

        cls_change_ex
            Allow student to change exercise.
        cls_def_pw_account
            Class default account password.
        cls_def_pw_console
            Class default console password.
        cls_def_pw_enable
            Class default enable password.
        cls_email_logs
            Email reservation logs for real equipment pods. (N=No, P=Email primary instructor)
        cls_end_date
            Class end date.
        cls_id
            Unique class identifier.
        cls_lab_limit
            Lab limit settings. (E=Enforce class lab limit, I=Instructor override)
        cls_max_slots_per_res
            Maximum number of slots per reservation.
        cls_min_hours_btw_res
            Minimum number of hours between reservations.
        cls_name
            Unique class name per community.
        cls_no_delete
            Prevent from deletion.
        cls_retain_ilt
            Retain instructor led logs.
        cls_retain_period
            Number of days to retain class logs.
        cls_retain_st
            Retain student logs.
        cls_self_sched
            Allow students to self schedule.
        cls_start_date
            Class start date.
        cls_team_sched
            Allow teams to schedule.
        cls_uuid
            Class UUID.
        com_id
            Unique community identifier.
        enrollment
            Count of those enrolled.
        leads
            List of leads and properties sorted by acc_sort_name.
        """

        method = "class.get"
        if properties == 'all':
            properties = self.class_props
        if properties == 'default':
            properties = self.class_default_props
        return self.call(method, cls_id=cls_id, properties=properties, **kwargs)

    def class_update(self, *, cls_id, cls_change_ex=None, cls_def_pw_account=None, cls_def_pw_console=None,
                     cls_def_pw_enable=None, cls_email_logs=None, cls_end_date=None, cls_lab_limit=None,
                     cls_max_slots_per_res=None, cls_min_hours_btw_res=None, cls_name=None, cls_no_delete=None,
                     cls_retain_ilt=None, cls_retain_period=None, cls_retain_st=None, cls_self_sched=None,
                     cls_start_date=None, cls_team_sched=None, **kwargs):
        """
        This method allows you to update a class and its properties.

        :param str cls_id: Unique class identifier.

        :param bool cls_change_ex: Allow student to change exercise.
        :param str cls_def_pw_account: Class default account password.
        :param str cls_def_pw_console: Class default console password.
        :param str cls_def_pw_enable: Class default enable password.
        :param str cls_email_logs: Email reservation logs for real equipment pods:
                               'N' - Don't email logs
                               'P' - Email to primary instructor
        :param datetime.date cls_end_date: Class end date.
        :param str cls_lab_limit: Class lab time limit: 'E' - Enforce time limit or 'I' - Ignore time limit.
        :param int cls_max_slots_per_res: Maximum number of slots per reservation.
        :param int cls_min_hours_btw_res: Minimum hours between reservations.
        :param str cls_name: Class name.
        :param bool cls_no_delete: Prevent from deletion.
        :param bool cls_retain_ilt: Retain instructor led logs.
        :param int cls_retain_period: The number of days to retain logs for.
        :param bool cls_retain_st: Retain student logs.
        :param bool cls_self_sched: Allow students to self schedule.
        :param datetime.date cls_start_date: Class start date.
        :param bool cls_team_sched: Allow teams to schedule.

        :return: OK or Error
        """

        method = "class.update"
        params = {'cls_id': cls_id}

        if cls_name:
            params['cls_name'] = cls_name
        if cls_start_date:
            params['cls_start_date'] = cls_start_date
        if cls_end_date:
            params['cls_end_date'] = cls_end_date
        if cls_def_pw_account:
            params['cls_def_pw_account'] = cls_def_pw_account
        if cls_def_pw_console:
            params['cls_def_pw_console'] = cls_def_pw_console
        if cls_def_pw_enable:
            params['cls_def_pw_enable'] = cls_def_pw_enable
        if cls_email_logs:
            params['cls_email_logs'] = cls_email_logs
        if cls_lab_limit:
            params['cls_lab_limit'] = cls_lab_limit
        if cls_no_delete is not None:
            params['cls_no_delete'] = cls_no_delete
        if cls_retain_ilt is not None:
            params['cls_retain_ilt'] = cls_retain_ilt
        if cls_retain_st is not None:
            params['cls_retain_st'] = cls_retain_st
        if cls_retain_period:
            params['cls_retain_period'] = cls_retain_period
        if cls_self_sched is not None:
            params['cls_self_sched'] = cls_self_sched
        if cls_team_sched is not None:
            params['cls_team_sched'] = cls_team_sched
        if cls_change_ex is not None:
            params['cls_change_ex'] = cls_change_ex
        if cls_min_hours_btw_res:
            params['cls_min_hours_btw_res'] = cls_min_hours_btw_res
        if cls_max_slots_per_res:
            params['cls_max_slots_per_res'] = cls_max_slots_per_res

        params.update(kwargs)
        return self.call(method, **params)

    def class_remove(self, *, cls_id, delete_students=False, **kwargs):
        """
        This method allows you to remove a class from the NETLAB+ system.

        :param str cls_id: Unique class identifier.
        :param bool delete_students: Delete student accounts as well.

        :return: OK or Error
        """

        method = "class.remove"
        return self.call(method, cls_id=cls_id, delete_students=delete_students, **kwargs)

    def class_roster_add(self, *, acc_id, cls_id, lead=False, ros_team=None, **kwargs):
        """
        This method allows you to add a member to a class roster.

        :param str acc_id: Unique account identifier.
        :param str cls_id: Unique class identifier.
        :param bool lead: Add as lead.
        :param str ros_team: Assign user to a team. Single character, A-Z.

        :return: OK or Error
        """

        method = "class.roster.add"
        params = {'acc_id': acc_id, 'cls_id': cls_id, 'lead': lead}

        if ros_team:
            params['ros_team'] = ros_team

        params.update(kwargs)
        return self.call(method, **params)

    def class_roster_list(self, *, cls_id, leads=False, properties="default", **kwargs):
        """
        This method lists users in the class roster.

        :param str cls_id: Unique class identifier.
        :param bool leads: Retrieve **only** leads.
        :param properties: List of properties to retrieve.
        :type properties: str, list

        :return: On success, returns an object with the requested properties:

        **Properties**

        acc_display_name
            Account name people will see this name in discussions, messages and comments.
        acc_email
            Account email.
        acc_full_name
            Account full name.
        acc_last_login
            Timestamp of last account login.
        acc_logins
            Number of times a user has logged in.
        acc_sort_name
            Account name as it appears in sorted lists.
        acc_time_last_access
            Timestamp of last access.
        acc_type
            Account type: 'S': Student, 'I': Instructor
        acc_user_id
            Account user identifier.
        """

        method = "class.roster.list"
        if properties == 'all':
            properties = self.roster_props
        if properties == 'default':
            properties = self.roster_default_props
        return self.call(method, cls_id=cls_id, leads=leads, properties=properties, **kwargs)

    def class_roster_remove(self, *, acc_id, cls_id, **kwargs):
        """
        This method removes a user from the class roster.

        :param str acc_id: Account identifier of user to be removed.
        :param str cls_id: Unique class identifier.

        :return: OK or Error
        """

        method = "class.roster.remove"
        return self.call(method, acc_id=acc_id, cls_id=cls_id, **kwargs)
