;; A emacs package to help with templating soplex

;; For making case replace as case sensitive
(customize-set-variable case-fold-search  nil)

(defun hpp-rename (buff)
  ;; Rename the .cpp or .h file with hpp
  (if (string-match-p (regexp-quote "\.h") buff) ;Check if it is a .h file or
                                                 ;.cpp
      (replace-regexp-in-string "\.h" ".hpp" buff)
    (replace-regexp-in-string "\.cpp" ".hpp" buff)))

(defun soplex-replace (what with)
  ;; Helper function to do replacements in buffer
  (beginning-of-buffer)
  (while (search-forward what nil t)
    (replace-match with nil t)))

(defun soplex-replace-regexp (what with)
  ;; Helper function to do replacements in buffer
  (beginning-of-buffer)
  (while (search-forward-regexp what nil t)
    (replace-match with nil t)))

;; For making changes inside the cpp file
(defun soplex-transform-cpp ()
  ;;
  (interactive)

  (soplex-changes)
  (save-buffer)

  (do-rename)
  )

;; A helper function
(defun soplex-changes ()
  ;; The changes that happens to the buffer
    ;; Basic changes
    (soplex-replace "template <>" "template <class R>") ;Do find and replace
    (soplex-replace "<Real>" "<R>")
    ;; todo: a better way is to use \_> and \_<
    ;; VectorClasses
    (soplex-replace-regexp "\\bVectorReal\\b" "VectorBase<R>")
    (soplex-replace-regexp "\\bVector\\b" "VectorBase<R>")

    (soplex-replace-regexp "\\bDSVectorReal\\b" "DSVectorBase<R>")
    (soplex-replace-regexp "\\bDSVector\\b" "DSVectorBase<R>")

    (soplex-replace-regexp "\\bDVectorReal\\b" "DVectorBase<R>")
    (soplex-replace-regexp "\\bDVector\\b" "DVectorBase<R>")

    (soplex-replace-regexp "\\bSVectorReal\\b" "SVectorBase<R>")
    (soplex-replace-regexp "\\bSVector\\b" "SVectorBase<R>")

    (soplex-replace-regexp "\\bSSVector\\b" "SSVectorBase<R> ")
    (soplex-replace-regexp "\\bSSVectorReal\\b" "SSVectorBase<R> ")
    (soplex-replace-regexp "\\bSVSet\\b" "SVSetBase<R> ")

    (soplex-replace-regexp "\\bSPxLPReal\\b" "SPxLPBase<R>")
    (soplex-replace-regexp "\\bSPxLP\\b" "SPxLPBase<R>")

    (soplex-replace-regexp "\\bLPRow\\b" "LPRowBase<R>")
    (soplex-replace-regexp "\\bLPRowSet\\b" "LPRowSetBase<R>")

    (soplex-replace-regexp "\\bLPCol\\b" "LPColSetBase<R>")
    (soplex-replace-regexp "\\bLPColSet<R>\\b" "LPColSetBase<R>")

    ;; Real to R
    (soplex-replace-regexp "\\bReal\\b" "R")

)


(defun do-rename ()
    ;; change the extension of the current buffer from .cpp to .hpp
    (rename-file (buffer-name) (replace-regexp-in-string "\.cpp" ".hpp" (buffer-name)
                                                         )
                 )
  )



;; Only one instance of the file should be open
(defun soplex-move-to-hpp (beg end)
  ;; Move the region to corresponding hpp file
  (interactive "r")
  (setq buffname (buffer-name))
  (message buffname)
  (kill-region beg end)                 ;Kill the region
  (save-buffer)
  (with-temp-buffer                     ;Do everything in the temp buffer now
    (yank)                              ;Paste the killed region

    (soplex-changes)

    (setq cont (buffer-string))
    ;; Go to corresponding file and do the thing
    (find-file (hpp-rename buffname))
    (end-of-buffer)
    (insert cont)
    ;; (spacemacs/indent-region-or-buffer) ;TODO instead of indenting the whole
                                        ;buffer, only indent the required lines.
                                        ;Would improve the performance well.
    (save-buffer)
    (kill-buffer)
    ))

;; Set keybinding for soplex-move-to-hpp and soplex-transform-cpp
(global-set-key (kbd "M-p") 'soplex-move-to-hpp)
(global-set-key (kbd "M-C-p") 'soplex-transform-cpp)
;; todo, implement the rename function in transform cpp part?