;;; org-concept.el
;;
;; - Start with simple implementation of org-concept-expand:
;;   - Only valid links (to elements) within 1 file
;;   - Assumo only valid content (don't check)
;;   - Assume only using top level headlines and plainlists
;;   - On headlines: deflate:
;;     - ** becomes +
;;     - + becomes -
;;   - On plain list: inflate:
;;   - item becomes **

(defun org-concept-expand (element-at-point)
   "Expand the current element by searching the requested template"
   ;; interactive function: need 
   ;;  - org-element on the current line (get link within,
   ;;   name and tag, start with just link and name)
   ;;  - (upper-level element), not sure if required
   ;;  -location of org-element
   ;;  -the current buffer

   (interactive
    (let (element-at-point)
      (forward-char) ;to make sure you have item (no plain-list) 
      (setq element-at-point (org-element-at-point))
      (list element-at-point)))

   ;; FOCUS ON AREA: Use mark-subtree and narrow-region
   (org-up-heading-safe)
   (let ((headline-up (org-element-at-point)))
     (narrow-to-region
      (org-element-property ':begin headline-up)
      (org-element-property ':end headline-up)))
   (goto-char (+ 1 (org-element-property ':begin element-at-point)))
   
   ;; SPLIT FUNCTIONALITY:
   ;; If element is a top level headline, start org-concept-expand-headline. Elif element is plain-list or item, start org-concept-expand-item
   (if (eq 'headline (org-element-type element-at-point))
       (org-concept--expand-headline (element-at-point))
     (if (org-in-item-p)
     ;;Hard one, as only first + is plain list, rest is eighter item, paragragh or something else depending on position. Since only  expansion of top level plain list items is allowed, we can safely keep on using the parent, UNTILL it's parent is the plain-list type. 	
	 (progn
	   (setq parentElementType (org-element-type (org-element-property ':parent element-at-point)))
	   (while (not (eq 'plain-list parentElementType))
	     (setq element-at-point (org-element-property ':parent element-at-point))
	     (setq parentElementType (org-element-type (org-element-property ':parent element-at-point))))
	   (org-concept--expand-item element-at-point))
       (message "'org-concept-expand' requires position on heading or list item ")))

   (widen)
   )

(global-set-key "\C-c\C-x\C-e" 'org-concept-expand)

(defun org-concept--expand-item (item)
  ;; First implementation
  ;; - only valid for top level items
  ;; - only with links pointing to elements within the file
  ;;
  ;; ! If you are working in the tree and need to return to item:
  ;;  (goto-char (+ (org-element-property ':begin item) 1))
  ;; Otherwise you get the plain-list or a paragraph
  ;; Returns t if expansion was success, nil otherwise

  (setq ast (org-element-parse-buffer))
  (setq parent (org-element-contents ast))
  ;; ! to get property use (car parent),
  ;; double braces around content
  
  ;; PART 1: creating subheading, based on owning headline
  ;; 1.1: Creating dummy headline
  ;;  (been looking at org-dp, but don't like it...)
  (goto-char (point-max))
  (newline)
  (goto-char (-(point-max) 1))
  (insert "* ")
  (setq item-as-headline (org-element-headline-parser (point) 1))
  (delete-region (- (point-max) 3) (point-max))

  ;; 1.2: Modify properties
  (let (level tags title)
    (setq level (+ 1 (org-element-property ':level (car parent))))
    ;; (buffer-substring) also takes into account text properties, like font. I only need pure characters.
    (setq tags (buffer-substring-no-properties
    		(org-element-property ':contents-begin item)
    		(- (org-element-property ':contents-end item) 1)))
    (setq title "TODO: ask title, default value: <tag>-number")
    
    (org-element-put-property item-as-headline ':level level)
    (org-element-put-property item-as-headline ':tags tags)
    
    (org-element-put-property item-as-headline ':title title)
    (org-element-put-property item-as-headline ':raw-value title))

  ;; PART 2: modifying item (eg. counter)
  ;; (Not in first implementation)

  ;; PART 3: integration
  ;;(debug)
  ;; Just checkingPH
  ;;(org-element-interpret-data ast) ;; for comparison
  ;;(org-element-headline-interpreter item-as-headline nil)
  
  ;;(setq test (org-element-adopt-elements parent item-as-headline))
  ;;  (org-element-interpret-data test)

 ;; (org-element-set-contents ast test)
 ;; (org-element-interpret-data ast) 
;  (org-element-adopt-elements parent newhl)
)
  
(defun org-concept--expand-headline (point)
  ;; First implementation
  ;; - only valid for top level headlines
  ;; - only with links pointing to elements within the file
  ;; Returns t if expansion was success, nil otherwise

  (catch 'notYetImplemented
  ;; Project in initial phase: TODO's all around
  (if (not (eq '1 (org-element-property ':level element)))
     (throw 'notYetImplemented (message "notYetImplemented: Expanding sub-headlines")))
  (if (org-element-property ':tag element)
     (throw 'notYetImplemented (message "notYetImplemented: Reverse checkup of tags")))

  ;; (debug)
  ;; (message (prin1-to-string element))
  ;; Output of org-element-at-point
  ; On a headline(headline (:raw-value "Brainstorming" :begin 6018 :end 8762 :pre-blank 0 :hiddenp outline :contents-begin 6034 :contents-end 8752 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 3 :footnote-section-p nil :archivedp nil :commentedp nil :quotedp nil :CATEGORY "CREATE" :title "Brainstorming")))
  
  ;; PART 1: Get concepts defining element
  ;; Part 1.1: Creating a property list with elements in link.
  
;;  (setq org-concept-plist (org-concept-split-line))
  
  ;; Part 1.2: Get a list containing the org-elements of concepts
  ;; PART 2: 

  
  ))

(defun org-concept--split-line (line)
  ;; Checks the current line if:
  ;; - Links are available
  ;; - Links are valid
  ;; - (TODO) Create reverse link for TAG
  ;; - (MAYBE) Put restriction on name: Not more than
  ;;    1 sentence or maximum number of characters.
  ;;
  ;; If no link found: call org-concept-check which searches link based on plain text.
  ;;
  ;; Returns:
  ;; - plist (item, values) for every element
  ;; - Nill if any problem is detected
  ;; - Final implementation should NEVER return nill, but call the apropriate functions to solve the problem.
  (message "TODO: Line-tester")
  'nil
  )

(defun org-concept--check ()
  ;; Functionalities:
  ;; If there is no link: check if plain text concept exists and add link. Ask if org-concept-expand is required. If there is link: check if the expansion is still correct compared to link (+ recursive for headline + all items)
  (message "TODO: checker")
  'nil
  )
 
;; Output of org-element-at-point
; On a headline(headline (:raw-value "Brainstorming" :begin 6018 :end 8762 :pre-blank 0 :hiddenp outline :contents-begin 6034 :contents-end 8752 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 3 :footnote-section-p nil :archivedp nil :commentedp nil :quotedp nil :CATEGORY "CREATE" :title "Brainstorming")))
;; Output of org-element-at-point
; On a list item ("Line 95" (plain-list (:type unordered :begin 6084 :end 6272 :contents-begin 6084 :contents-end 6272 :structure ((6084 0 "- " nil nil nil 6125) (6125 0 "- " nil nil nil 6160) (6160 0 "- " nil nil nil 6272) (6225 2 "- " nil nil nil 6272)) :post-blank 0 :post-affiliated 6084 :parent nil)))

(defun test (subject)
    (interactive
     (let (subject)
       (setq subject (org-element-at-point))
       (list subject)))

    (debug)
    (setq element-at-point subject)
    )
  (debug)
  (setq content (org-element-contents (org-element-parse-buffer)))
  ;; Cant really use 
;  (setq element-lineage (org-element-lineage subject))
  ;; OK to use
  ;; (setq element-current (org-element--current-element (org-element-property ':begin subject)))
  ;; (setq element-string (buffer-substring (org-element-property ':begin subject) (org-element-property ':end subject)))
  ;; (setq element-parseSecString (org-element-parse-secondary-string  element-string '(link ...)))
  ;; (setq greater-element-parse (org-element-item-parser (org-element-property ':begin subject) (org-list-struct)))
  ;; (debug)
  ;; (setq element-parse (org-element--parse-elements (org-element-property ':begin (org-element-at-point)) (org-element-property ':end (org-element-at-point)) 'first-section  nil 'element nil nil))
  ;;(message (prin1-to-string element-at-point))
  ;;(message (prin1-to-string element-lineage))
  ;;  (message (prin1-to-string element-current))
  (message (prin1-to-string content))
  ;;(message (prin1-to-string greater-element-parse))
  ;; (message (prin1-to-string contents))
  
  )

;; example
(defun triangle-recursively-bugged (number)
  "Return sum of numbers 1 through NUMBER inclusive.Uses recursion."
  (if (= number 1)
      1
    (+ number
       (triangle-recursively-bugged
	(1= number)))))			; Error here.
(triangle-recursively-bugged 3)


;; Messing with org-list, plain lists
;; 	 (progn (
   ;; 		 (setq structure (org-list-struct)))))))


   
  ;;  (setq item (org-in-item-p))
  ;;  (setq struct (org-list-struct))
  ;;  (setq prevs (org-list-prevs-alist struct))
  ;;  (setq parents (org-list-parents-alist struct))

  ;;  (message (prin1-to-string item))
  ;;  (message (prin1-to-string struct))
  ;;  (message (prin1-to-string prevs))
  ;;  (message (prin1-to-string parents))

  ;;  (message (prin1-to-string (org-list-get-top-point struct)))
  ;;     (message (prin1-to-string (org-list-get-parent item struct parents)))
  ;;  (message (prin1-to-string (org-list-get-list-begin item struct prevs))))


    

