(defvar tintin-mode-hook nil)

(defvar tintin-mode-map
  (let ((map (make-keymap)))
    (define-key map "\C-j" 'newline-and-indent) ;placeholder
    map)
  "Keymap for tintin major mode")

; autoload tintin-mode for *.tin
(add-to-list 'auto-mode-alist '("\\.tin\\'" . tintin-mode))


(let (
      (red "#c95d5d") ;
      (green "#359440") ;
      (yellow "#c3c95d") ;
      (off-yellow "#c3b95d") ;
      (orange "#ef6d22")
      (blue "#5d74c9") ;
      (cyan "#5dc9c9") ;
      (off-cyan "#5db9c9") ;
      (white "#ffffff") ;
      (purple "#a95dc9") ;
     )

  (defface tintin-ansi-face
    `((t (:foreground ,red)))
    "*Face for ansi color codes."
    :group 'tintin-faces :group 'faces)
  (defface tintin-symbol-face
    `((t (:foreground ,white)))
    "*Face for symbols."
    :group 'tintin-faces :group 'faces)
  (defface tintin-var-face
    `((t (:foreground ,yellow)))
    "*Face for variables."
    :group 'tintin-faces :group 'faces)
  (defface tintin-var-def-face
    `((t (:foreground ,off-yellow)))
    "*Face for variable definitions."
    :group 'tintin-faces :group 'faces)
  (defface tintin-conditional-face
    `((t (:foreground ,purple)))
    "*Face for #Ifs, #Loops."
    :group 'tintin-faces :group 'faces)
  (defface tintin-comment-face
    `((t (:foreground ,green)))
    "*Face for comments."
    :group 'tintin-faces :group 'faces)
  (defface tintin-function-face
    `((t (:foreground ,cyan)))
    "*Face for user functions."
    :group 'tintin-faces :group 'faces)
  (defface tintin-function-def-face
    `((t (:foreground ,off-cyan)))
    "*Face for user function definitions."
    :group 'tintin-faces :group 'faces)
  (defface tintin-hash-face
    `((t (:foreground ,blue)))
    "*Face for user hash commands."
    :group 'tintin-faces :group 'faces)

)

; helps make the messy optimized regexps
(regexp-opt '(
"#v" "#V"
) t)

(defconst tintin-font-lock-keywords
  (list
   ; Comments.
   '("\\(#\\(?:N[Oo]\\|no\\)\\).*" . 'tintin-comment-face)
   ; Vars.
   '("\\(\%\\([a-zA-Z][a-zA-Z0-9]*\\|[0-9]*\\)\\)" . 'tintin-var-face)
   ; More Vars
   '("\\($[a-zA-Z_][][a-zA-Z0-9_]*\\)" . 'tintin-var-face)
   ; and more, the #VAR now
   '("\\(#\\(?:V\\(?:AR\\(?:I\\(?:A\\(?:B\\(?:LE?\\)?\\)?\\)?\\)?\\|ar\\(?:i\\(?:a\\(?:b\\(?:le?\\)?\\)?\\)?\\)?\\)\\|var\\(?:i\\(?:a\\(?:b\\(?:le?\\)?\\)?\\)?\\)?\\)\\) *\\([a-zA-Z_][][a-zA-Z0-9_-]*\\|{ *[a-zA-Z_][][ a-zA-Z0-9_-]*}\\)\\([ \t\n]\\| .?\\)" . 'tintin-var-def-face)
   ; User functions. If the function args have quotes it fails... WTF is with the quotes anyway???
   '("\\(@[a-zA-Z_][][a-zA-Z0-9_]*\\) *{[^}]*}" . 'tintin-function-face)
   ; User functions, definitions.
   '("\\(#\\(?:F\\(?:UN\\(?:C\\(?:T\\(?:I\\(?:ON?\\)?\\)?\\)?\\)?\\|un\\(?:c\\(?:t\\(?:i\\(?:on?\\)?\\)?\\)?\\)?\\)\\|fun\\(?:c\\(?:t\\(?:i\\(?:on?\\)?\\)?\\)?\\)?\\)\\) *\\([a-zA-Z_][][a-zA-Z0-9_-]*\\|{ *[a-zA-Z_][][ a-zA-Z0-9_-]*}\\)\\([ \t\n]\\| .?\\)" . 'tintin-function-def-face)
   ; #IF #IFELSE #ELSE and #LOOP.
   '("\\(#\\(?:E\\(?:LSE\\(?:IF\\)?\\|lse\\(?:[Ii]f\\)?\\)\\|I[Ff]\\|L\\(?:OOP\\|oop\\)\\|else\\(?:if\\)?\\|if\\|loop\\)\\)[ \t\n]" . 'tintin-conditional-face)
   ; Colours.
   '("\\(\<[0-9]*\>\\)" . 'tintin-ansi-face)
   ; Curly brackets etc.
   '("\\([][(){};\+\*\-\/]\\)" . 'tintin-symbol-face)
   ; All possible '#' commands, even '#EOUOEU'. Yes, I'm lazy.
   '("\\(#[a-zA-Z0-9]*\\)[ \t\n]" . 'tintin-hash-face)
  )
  "Default highlighting for tintin mode")

(defvar tintin-mode-syntax-table
  (let ((st (make-syntax-table)))

    (modify-syntax-entry ?_ "w" st) ; sets underscore to be counted as one_word

    st)
  "Syntax table for tintin-mode")

(defun tintin-mode ()
  "Major mode for editing tintin config files"
  (interactive)
  (kill-all-local-variables)
  (set-syntax-table tintin-mode-syntax-table)
  (use-local-map tintin-mode-map)

  (set (make-local-variable 'font-lock-defaults) '(tintin-font-lock-keywords))

  (setq major-mode 'tintin-mode)
  (setq mode-name "tintin++")
  (run-hooks 'tintin-mode-hook)
)

(provide 'tintin-mode)