;;; slack-selectable.el ---                          -*- lexical-binding: t; -*-

;; Copyright (C) 2018

;; Author:  <yuya373@yuya373>
;; Keywords:

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;;

;;; Code:

(require 'eieio)
(require 'slack-util)

(defvar slack-completing-read-function)

(defclass slack-selectable ()
  (
   ;; one of users, channels, conversations, external or static
   (data-source :initarg :data_source :type string :initform "static")
   (options :initarg :options :initform nil)
   (option-groups :initarg :option_groups :initform nil)
   (selected-options :initarg :selected_options :type (or null list) :initform '())
   ))

(defclass slack-selectable-option ()
  ((text :initarg :text :type string)
   (value :initarg :value :type string)))

(defclass slack-selectable-option-group ()
  ((text :initarg :text :type string)
   (options :initarg :options :initform nil)))

(cl-defmethod slack-selectable-prompt ((_this slack-selectable))
  "")


(cl-defmethod slack-selectable-text ((this slack-selectable-option))
  (oref this text))

(cl-defmethod slack-selectable-text ((this slack-selectable-option-group))
  (oref this text))

(cl-defmethod slack-selectable-select-from-static-data-source ((this slack-selectable))
  (cl-labels
      ((select-option (options)
                      (select (slack-selectable-prompt this)
                              (mapcar #'(lambda (option)
                                          (cons (slack-selectable-text option)
                                                (oref option value)))
                                      options)))
       (select-option-group
        (option-groups)
        (slack-if-let*
            ((text (select (slack-selectable-prompt this)
                           (mapcar #'(lambda (option-group)
                                       (slack-selectable-text option-group))
                                   option-groups))))
            (find-option text option-groups)))
       (find-option (text options)
                    (cl-find-if #'(lambda (option)
                                    (string= text (slack-selectable-text option)))
                                options))
       (select (prompt options)
               (funcall slack-completing-read-function
                        prompt
                        options
                        nil t)))
    (with-slots (options option-groups) this
      (slack-if-let*
          ((options (if option-groups
                        (oref (select-option-group option-groups)
                              options)
                      options))
           (option-text (select-option options)))
          (find-option option-text options)))))

(provide 'slack-selectable)
;;; slack-selectable.el ends here
