;; (looking-at cbrow--is-inside-a-class--regexp)
;; (cbrow--is-inside-a-class)
;; WTF? does this function do?
(defun cbrow--is-inside-a-class ()
  (interactive)
  (let ((p (point)))
    (save-match-data
      (save-excursion
        (cond
         ((looking-at cbrow--is-inside-a-class--regexp))
         ((and (looking-at "^{")
               (progn
                 (forward-line -1)
                 (looking-at cbrow--is-inside-a-class--regexp))))

         ((re-search-backward "^{" nil t)
          (forward-line -1)
          (and (looking-at cbrow--is-inside-a-class--regexp)
               (progn (forward-line 1)
                      (beginning-of-line)
                      (assert (looking-at "^{"))
                      (forward-sexp 1) ;;; skip to end of class definition
                      (> (point) p)))))))))

;; (setq class nil)
;; (not nil)
(global-set-key [kp-enter] (function (lambda () (interactive)
                                       (message "cbrow-find-class=%s" (cbrow--inside-class)))))

;; 
;; WTF? does this method do?
(d-quote defun cbrow--find-class ()
  (save-match-data
    (save-excursion
      (let ((class (cbrow--inside-class)))
        (cond
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
         ((string= (buffer-name) cbrow--buffer-name)
          (progn
            (goto-char (point-min))
            (when (re-search-forward (concat "^class") nil t)
              (skip-chars-forward " \t")
              ;;(if (looking-at "[a-zA-Z0-9_]+::\\([a-zA-Z0-9_]+\\)")
              ;;    (buffer-substring-no-properties (match-beginning 1)
              ;;                                    (match-end 1))
              (if (looking-at (concat "[" cbrow--identifier-chars ":]"))
                  (buffer-substring-no-properties (point)
                                                  (save-excursion
                                                    (skip-chars-forward (concat cbrow--identifier-chars ":"))
                                                    (point)))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
         ((eq major-mode 'c++-mode)
          (setq *namespace* (cbrow--inside-namespace))
          ;;(debug "Rocket man")
          (cond
           ((cbrow--is-inside-a-class)
            (if 'apple (cbrow--is-inside-a-class--find-class)))
           ((cbrow--is-inside-an-outer-method)
            (if 'banana (car (cbrow--is-inside-an-outer-method--find-class-&-method))))
           (t
            nil)))
         (t
          nil))))))

(d-quote
 (skip-chars-forward " \t")
 (skip-chars-forward "A-Z0-9_")
 (skip-chars-forward " \t")
 (if *verbose* (skip-chars-forward "K: \t"))
 (cbrow--skip-word "class")
 (skip-chars-forward " \t")
 (setq p1 (point))
 (skip-chars-forward "a-zA-Z0-9_:")
 (setq p2 (point))
 (setq str (buffer-substring-no-properties p1 p2))
 ;;(debug "Libido")
 (if *namespace* (concat *namespace* "::" str) str))

(d-quote
  ;;(debug "Calamansi")
  (if (looking-at "[a-zA-Z0-9_]")
      (let (p1 p2 s)
        (save-excursion
          (skip-chars-backward "a-zA-Z0-9_")
          (setq p1 (point))
          (skip-chars-forward "a-zA-Z0-9_")
          (setq p2 (point))
          (setq s (buffer-substring-no-properties p1 p2))
          ;;(debug "Splitter")
          (if (assoc s cbrow--header-alist)
              s
            nil)))))

;; (cbrow--a-is-a-direct-superclass-of-b "A1" "A")
;; (cbrow--a-is-a-direct-superclass-of-b "A" "Z")
;; (cbrow--a-is-a-direct-superclass-of-b "Z" "A")
(defun cbrow--a-is-a-direct-superclass-of-b (a b)
  (let* ((superclasses-of-b (cdr (assoc b cbrow--superclass-alist)))
         (ptr               superclasses-of-b)
         (found             nil))
    (while (and ptr (not found))
      (if (string= (car ptr) a)
          (setq found t))
      (setq ptr (cdr ptr)))
    found)
  )

;; (setq superclass "A1")
;; (setq subclass   "A")
;; (cbrow--less-than "A1" "A") => t
;; (cbrow--less-than "A" "A1") => nil
;; (cbrow--less-than "A1" "Z") => t
;; (cbrow--less-than "Z"  "A1") => nil
;; (cbrow--less-than "A"  "Z")
;; (cbrow--less-than "Z"  "A")
;;;
;;; order is A1,A2,A,Z
;;;
(d-quote defun cbrow--less-than (a b)
  (or (cbrow--a-is-a-direct-superclass-of-b a b)
      (let* ((superclasses-of-b (cdr (assoc b cbrow--superclass-alist)))
             (ptr               superclasses-of-b)
             (found             nil))
        (while (and ptr (not found))
          (if (not found)
              (setq found (cbrow--less-than a (car ptr))))
          (setq ptr (cdr ptr)))
        found))
  )

(d-quote defun cbrow--bubble-sort--swap (list i j)
  (let ((si  (nth i list))
        (sj  (nth j list))
        (ptr list))
    (while ptr
      (cond
       ((string= (car ptr) si)
        (setcar ptr sj))
       ((string= (car ptr) sj)
        (setcar ptr si)))
      (setq ptr (cdr ptr)))
    list))

;; (setq list '("Apple" "Smeg" "Zorro"))
;; (setq less-than-func 'cbrow--less-than)
;;;
;;; Does this always work?
;;; perhaps need to check that (< i j) is true
;;;
(d-quote defun cbrow--bubble-sort (list less-than-func)

  (let ((i   0)
        (len (length list)))
    (while (< i len)
      (let ((j 0))
        (while (< j len)
          ;;(if (< i j)
          (if (apply less-than-func (list (nth i list) (nth j list)))
              (cbrow--bubble-sort--swap list i j)
            )
          ;;(message "(%s %s %s)"
          ;;         less-than-func
          ;;         (prin1-to-string (nth i list))
          ;;         (prin1-to-string (nth j list)))

          ;;)
        (incf j)))
      (incf i))
    list)
  )

(d-quote
 (let ((done nil))
   (while (and (not done)
               (save-excursion
                 (goto-char (point-min))
                 (not (re-search-forward (format "//LINE:%s" line) nil t))))
     (if (/= 0 line)
         (decf line)
       (setq done t)))
   (beginning-of-line))
 (goto-char (point-min))
 (when (re-search-forward (format "//LINE:%s" line) nil t)
   (beginning-of-line))
 )

((save-excursion
   (and (not *namespace*)
        (save-excursion
          (forward-line 1)
          (beginning-of-line)
          (setq squiggly (point))
          (looking-at (if class "^[ ][ ][ ]" "^{")))
        (progn
          (goto-char squiggly)
          (forward-sexp -1)
          ;;(debug "carrotty smell")
          (beginning-of-line)
          (setq p (point))
          (goto-char squiggly)
          (beginning-of-line)
          (forward-sexp 1)
          (when (< orig (point))
            (goto-char p)
            (when (re-search-forward "\\(_?[a-zA-Z][a-zA-Z0-9_:]*\\)(" (point-at-eol) t)
              (setq found (buffer-substring-no-properties (match-beginning 1) (match-end 1))))))))
 found)

;; (cbrow--is-inside-outer-method--regexp)
(d-quote defun cbrow--inside-outer-method ()
  (interactive)
  (let (*namespace* namespace class method function)
    (setq *namespace* (cbrow--inside-namespace))
    (setq class       (cbrow--inside-class))
    (setq function    (cbrow--inside-function))
    (cond
     ((save-excursion
        (beginning-of-line)
        (looking-at (if *namespace* "^[ ][ ][ ][ ][ ][ ]{" "^[ ][ ][ ]{")))
      (save-excursion
        (forward-line -1)
        (beginning-of-line)
        ;;(debug "Banana cake")
        (cond
         ((looking-at (concat (if *namespace* "^[ ][ ][ ][ ][ ][ ]" "^[ ][ ][ ]") cbrow--inside-outer-method--regexp-1))
          (setq method (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
          )
         ((looking-at (concat (if *namespace* "^[ ][ ][ ][ ][ ][ ]" "^[ ][ ][ ]") cbrow--inside-outer-method--regexp-2))
          (setq class  (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
          (setq method (buffer-substring-no-properties (match-beginning 3) (match-end 3))))
         ((looking-at (concat (if *namespace* "^[ ][ ][ ][ ][ ][ ]" "^[ ][ ][ ]") cbrow--inside-outer-method--regexp-3))
          (setq namespace (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
          (setq class     (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
          (setq method    (buffer-substring-no-properties (match-beginning 3) (match-end 3)))
          ))
        (cons class method)))
     
     ((save-excursion
        (beginning-of-line)
        (forward-line 1)
        (looking-at (if *namespace* "^[ ][ ][ ][ ][ ][ ]{" "^[ ][ ][ ]{")))
      (save-excursion
        (beginning-of-line)
        ;;(debug "Carrotty")
        (cond
         ((looking-at (concat (if *namespace* "^[ ][ ][ ][ ][ ][ ]" "^[ ][ ][ ]") cbrow--inside-outer-method--regexp-1))
          (setq method (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
          )
         ((looking-at (concat (if *namespace* "^[ ][ ][ ][ ][ ][ ]" "^[ ][ ][ ]") cbrow--inside-outer-method--regexp-2))
          (setq class  (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
          (setq method (buffer-substring-no-properties (match-beginning 3) (match-end 3))))
         ((looking-at (concat (if *namespace* "^[ ][ ][ ][ ][ ][ ]" "^[ ][ ][ ]") cbrow--inside-outer-method--regexp-3))
          (setq namespace (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
          (setq class     (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
          (setq method    (buffer-substring-no-properties (match-beginning 3) (match-end 3)))
          ))
        (cons class method)))
     
     )))
     
(d-quote defun cbrow--inside-outer-method--find-class-&-method--inner ()
  (save-excursion
    (save-match-data
      (let ((class  nil)
            (method nil))
        ;;(message "Cur Line=%s" (d-current-line-as-string))
        (skip-chars-forward "A-Z")
        (skip-chars-forward " \t")
        (when (looking-at "class[ \t]")
          (skip-chars-forward "^:({\n\r") ;;; skip types and crud
          (setq class (buffer-substring-no-properties
                       (point)
                       (progn
                         (skip-chars-backward cbrow--identifier-chars)
                         (point))))
          (skip-chars-forward "^({\n\r")
          (setq method (buffer-substring-no-properties
                        (point)
                        (progn
                          (skip-chars-backward cbrow--identifier-chars)
                          (point))))
          (cons class method))))))

;; (cbrow--inside-outer-method--find-class-&-method)
(d-quote defun cbrow--inside-outer-method--find-class-&-method ()
  (save-excursion
    (let (answer)
      ;;(d-beeps "Currentbuffer=%s" (current-buffer))
      (cond
       ((save-excursion
          (forward-line 1)
          (and *namespace* (looking-at "^[ ][ ][ ]{")))
        (let (p1 p2)
          (save-excursion
            (re-search-forward "class[ \t]" (point-at-eol) t)
            (skip-chars-forward "a-zA-Z0-9_")
            (skip-chars-forward ":")
            (setq p1 (point))
            (skip-chars-forward "a-zA-Z0-9_")
            (setq p2 (point))
            (cons (concat *namespace* "::" (buffer-substring-no-properties p1 p2)) nil))))
       ((save-excursion
          (forward-line 1)
          (and (not *namespace*) (looking-at "^{")))
        (let (p1 p2)
          (save-excursion
            (re-search-forward "class[ \t]" (point-at-eol) t)
            (skip-chars-forward "a-zA-Z0-9_")
            (skip-chars-forward ":")
            (setq p1 (point))
            (skip-chars-forward "a-zA-Z0-9_")
            (setq p2 (point))
            (cons (buffer-substring-no-properties p1 p2) nil))))
       ;;
       ;; NOTE: on the line of the method
       ;;
       ((looking-at cbrow--inside-outer-method--regexp)
        (setq answer (cbrow--inside-outer-method--find-class-&-method--inner))
        ;;(if 123 (debug 123))
        )
       ;;
       ;; NOTE: on the line of the open brace
       ;;
       ((looking-at "^{")
        (forward-line -1)
        (setq answer (cbrow--inside-outer-method--find-class-&-method--inner))
        ;;(if 456 (debug 456))
        )
       ;;
       ;; NOTE: inside the method
       ;;
       ((re-search-backward "^{" nil t)
        (forward-line -1)
        ;;(d-beeps "Current buffer=%s" (current-buffer))
        (setq answer (cbrow--inside-outer-method--find-class-&-method--inner))
        ;;(if 789 (debug 789))
        )
       (t
        (error "Function cbrow--inside-outer-method--find-class-&-method: should never happen")))
      answer)))
;;(defun cbrow--is-inside-a-class--find-method ()
;;  (save-excursion
;;    (when (re-search-backward "^   {" nil t)
;;      (forward-line -1)
;;      (forward-sexp 1) ;;; skip "class"
;;      (skip-chars-forward " \t")
;;      (buffer-substring-no-properties (point) (progn (skip-chars-forward "A-Za-z0-9_")
;;                                                     (point))))))

(defun cbrow--is-inside-a-class--find-class ()
  (save-match-data
    (save-excursion
      (cond
       ((looking-at cbrow--inside-class--regexp)
        (progn
          (when (looking-at "[A-Z]*[ \t]*")
            (skip-chars-forward "A-Z")
            (skip-chars-forward " \t"))
          (cbrow--skip-word "class")
          (skip-chars-forward " \t")
          (buffer-substring-no-properties
           (point) (progn
                     (skip-chars-forward cbrow--identifier--chars) ;;; skip identifier
                     (point)))))
       ((looking-at "^{")
        (forward-line -1)
        (when (looking-at cbrow--inside-class--regexp)
          (when (looking-at "[A-Z]*[ \t]*")
            (skip-chars-forward "A-Z")
            (skip-chars-forward " \t"))
          (cbrow--skip-word "class")
          (skip-chars-forward " \t")
          (buffer-substring-no-properties
           (point)
           (progn
             (skip-chars-forward cbrow--identifier--chars) ;;; skip identifier
             (point)))))

       ((re-search-backward "^{" nil t)
        (forward-line -1)
        (when (looking-at cbrow--inside-class--regexp)
          (when (looking-at "[A-Z]*[ \t]*class[ \t]")
            (skip-chars-forward "A-Z")
            (skip-chars-forward " \t"))
          (cbrow--skip-word "class")
          (skip-chars-forward " \t")
          (buffer-substring-no-properties
           (point)
           (progn
             (skip-chars-forward cbrow--identifier--chars) ;;; skip identifier
             (point)))))))))

(defun cbrow--inside-method ()
  (save-match-data
    (save-excursion
      (let ((orig (point)) p *class* found squiggly result namespace-ps class-ps)
        (setq *namespace* (cbrow--inside-namespace))
        (setq *class*       (cbrow--inside-class))
      
        (if *namespace*
            (setq namespace-ps (cbrow--inside-namespace-p1-and-p2)))
        (if *class*
            (setq class-ps     (cbrow--inside-class-p1-and-p2)))

        ;;(debug "Salami Sandwiches")
      
        (if (and *class* (string-match (concat "\\(" *namespace* "::\\)") *class*))
            (setq *class* (substring *class* (match-end 1))))
      
        ;;(debug "Wanker of the week")

        (cond
         ((save-excursion
            ;;(forward-line -1)
            ;;(setq p (point))
            ;;(forward-line 1)
            (beginning-of-line)
            (when (looking-at (if *namespace* "^[ ][ ][ ][ ][ ][ ]{" "^[ ][ ][ ]{"))
              (setq squiggly (point))
              (forward-line -1)
              (setq p (point))
              (goto-char squiggly)
              (forward-sexp 1) ;;; SKIP SQUIGGLIES!
              (when (< orig (point))
                (goto-char p)
                ;;(re-search-forward (concat "^[ ][ ][ ]" cbrow--inside-method--regexp "(") nil t)
                (when (re-search-forward (concat (if *namespace* "^[ ][ ][ ][ ][ ][ ]" "^[ ][ ][ ]")
                                                 cbrow--inside-method--regexp "(")
                                         (if *namespace* (cdr namespace-ps) (cdr class-ps))
                                         t)
                  (setq found (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
                  (forward-char -1)
                  (setq p (point))
                  (forward-sexp 1) ;; SKIP ARGS!
                  (setq found (concat found (cbrow--change-args (buffer-substring-no-properties p (point)))))
                  ))))
          found)
         ((save-excursion
            (beginning-of-line)
            (setq p (point))
            (forward-line 1)
            (when (looking-at (if *namespace* "^[ ][ ][ ][ ][ ][ ]{" "^[ ][ ][ ]{"))
              (setq squiggly (point))
              (forward-sexp 1) ;; SKIP SQUIGGLIES!
              ;;(debug 456)
              (when (< orig (point))
                (goto-char p)
                (when (re-search-forward (concat (if *namespace* "^[ ][ ][ ][ ][ ][ ]" "^[ ][ ][ ]")
                                                 cbrow--inside-method--regexp "(")
                                         (if *namespace* (cdr namespace-ps) (cdr class-ps))
                                         t)
                  (setq found (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
                  (forward-char -1)
                  (setq p (point))
                  (forward-sexp 1) ; SKIP ARGS!
                  (setq found (concat found (cbrow--change-args (buffer-substring-no-properties p (point)))))
                  ))))
          found)
         ((save-excursion
            (when (re-search-backward (if *namespace* "^[ ][ ][ ][ ][ ][ ]{" "^[ ][ ][ ]{")
                                      (if *namespace* (car namespace-ps) (car class-ps))
                                      t)
              (setq squiggly (point))
              (forward-sexp -1) ;; SKIP ARGS!
              (beginning-of-line)
              (setq p (point))
              ;;(debug 789)
              (goto-char squiggly)
              (forward-sexp 1) ;; SKIP SQUIGGLIES!
              (when (< orig (point))
                (goto-char p)
                (when (re-search-forward (concat (if *namespace* "^[ ][ ][ ][ ][ ][ ]" "^[ ][ ][ ]")
                                                 cbrow--inside-method--regexp "(")
                                         (if *namespace* (cdr namespace-ps) (cdr class-ps))
                                         t)
                  (setq found (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
                  (forward-char -1)
                  (setq p (point))
                  (forward-sexp 1) ;; SKIP ARGS!
                  (setq found (concat found (cbrow--change-args (buffer-substring-no-properties p (point)))))
                  ;;(debug 789)
                  ))))
          found)
         
         ((save-excursion
            (and (not *namespace*)
                 (prog1
                     (re-search-backward (if *class* "^[ ][ ][ ]{" "^{")
                                         (car class-ps)
                                         t)
                   (setq squiggly (point)))
                 (progn
                   ;;(debug "Frogger")
                   ;;(forward-line -1)
                   ;;(end-of-line)
                   (forward-sexp -1) ;; SKIP ARGS!
                   (beginning-of-line)
                   (setq p (point))
                   ;;(forward-line 1)
                   (goto-char squiggly)
                   ;;(beginning-of-line)
                   (if 'zed (forward-sexp 1)) ;; SKIP SQUIGGLIES!
                   (when (< orig (point))
                     (goto-char p)
                     ;;(debug "smeg")
                     (when (re-search-forward (concat (if *class* "^[ ][ ][ ]" "^")
                                                      cbrow--inside-method--regexp "(") (point-at-eol) t)
                       (setq found (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
                       (forward-char -1)
                       (setq p (point))
                       (forward-sexp 1) ;; SKIP ARGS!
                       (setq found (cbrow--change-args (concat found (buffer-substring-no-properties p (point)))))
                       (debug "PI")
                       )))))
          found)
         
         ((save-excursion
            (and (not *namespace*)
                 (progn
                   (beginning-of-line)
                   (when (setq result (re-search-forward (if *class* "^[ ][ ][ ]{" "^{")
                                                         (cdr class-ps)
                                                         t))
                     (forward-char -1)
                     (setq squiggly (point))
                     ;;(debug "Roger Ramjet")
                     result))
                 (progn
                   ;;(beginning-of-line)
                   (forward-line -1)
                   (end-of-line)
                   (forward-sexp -1)
                   (beginning-of-line)
                   (setq p (point))
                   (goto-char squiggly)
                   ;;(forward-line 1)
                   (if 'id (forward-sexp 1))
                   ;;(debug 123)
                   (when (< orig (point))
                     (goto-char p)
                     ;;(debug 456)
                     (when (re-search-forward (concat (if *class* "^[ ][ ][ ]" "^")
                                                      cbrow--inside-method--regexp "(") (point-at-eol) t)
                       ;;(debug 789)
                       (setq found (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
                       ;;(debug "Zippo Lighters")
                       (forward-char -1)
                       (setq p (point))
                       (forward-sexp 1) ;; SKIP ARGS!
                       (setq found (cbrow--change-args (concat found (buffer-substring-no-properties p (point)))))
                       ;;(debug "Popsicles")
                       )))))
          found)
         )
        ;;(debug "Fynall Bynall")
        (if found
            (concat (if *namespace* (concat *namespace* "::"))
                    (if *class*       (concat *class* "::"))
                    found))
        ;;(debug "Cold Potatoes")
        )
      )
    )
  )
(d-quote
 (setq file (cadr (assoc *class* cbrow--header-alist)))
 (if (and file (file-exists-p file))
     (progn
       (debug "Banana split")
       (if 'apple-computers (find-file file))
       (cond
        ((re-search-forward (concat class-only "::" method-name-only "(") nil t)
;;;dmp::Foo::method1(
         (message "Here it is in the header file")
         (beginning-of-line))
        ((and (re-search-forward (concat class-only "::" method-name-only "(") nil t)
              (setq *namespace* (cbrow--inside-namespace))
              (string-match *namespace* method-name-plus-class))
;;;void Foo::method1(
         (message "Here it is in the header file")
         (beginning-of-line))))))

((setq result (cbrow--inside-method))
              (let ((*class*  (car result))
                    (method (cdr result)))
                ;;
                ;; NOTE: set number of args to search for...
                ;;
                (debug "foo")
                ;;(error "bar")
                (if 789 (cbrow--generate-browser *class* method))
                ;;(debug "123")
                (re-search-forward (concat "\\<" method "("))
                ))

;;(if class-only 
;;    (if (string-match (concat "\\(" class-only "\\)::\\(.*\\)$") method)
;;        (setq method (substring method
;;                                (match-beginning 2)
;;                                (match-end 2)))))

;;(if *class*
;;    (if (string-match (concat *namespace* "::\\(.*\\)") *class*)
;;        (setq class-only (substring *class* (match-beginning 1) (match-end 1)))))
;;
;;(assert (string= class-only "Dog"))
;;
;;(if class-only
;;    (if (string-match (concat "^" class-only "::\\(.*\\)") method)
;;        (setq method (substring method (match-beginning 1) (match-end 1)))))

;;(assert (string= "cat" method))

