(require 'ew-gnus) ;; for gnus-init-file

;;;;
;;;;;; Startup/Shutdown/Modeline/Minibuffer
;;;;

;; emacs --daemon should use tcp, not a local socket
(require 'server)
(setq server-host "127.0.0.1")
(setq server-use-tcp t)
(setenv "EDITOR" "emacsclient")
(setenv "EMACS_SERVER_FILE" (expand-file-name server-name server-auth-dir))
(let ((start nil)
      (file (getenv "EMACS_SERVER_FILE")))
  (if (file-exists-p file)
      (with-temp-buffer
        (insert-file-contents file)
        (if (re-search-forward "^\\(\\([[:digit:]]+\\.\\)\\{3\\}[[:digit:]]+\\):\\([[:digit:]]+\\) " nil t)
            (let ((ip (match-string 1))
                  (port (match-string 3)))
              (condition-case e
                  (delete-process (open-network-stream "servertest" (current-buffer) ip port))
                (error (setq start t))))
          (setq start t)))
    (setq start t))
  (if start (server-start) (message "Emacs Server already running!")))

;; no welcome message, start with empty scratch buffer, bigger message buffer
(setq inhibit-startup-message t
      initial-scratch-message nil
      inhibit-startup-buffer-menu t
      message-log-max 10000)

;; Don't make it easy to exit emacs
(global-unset-key "\C-x\C-c")
(global-unset-key "\C-z")
(global-unset-key (kbd "s-w"))
(global-unset-key (kbd "s-q"))
(global-unset-key (kbd "<ns-power-off>"))

(defun eaw-many-buffers-kill-hook ()
  "Query the user as to whether killing Emacs should be cancelled
when there are a lot of open buffers"
  (if (> (length (buffer-list)) 15)
      (yes-or-no-p
       "You have a lot of buffers open, are you sure you want to quit? ")
    t))
(add-to-list 'kill-emacs-query-functions 'eaw-many-buffers-kill-hook)
(setq confirm-kill-emacs 'yes-or-no-p)

;; revisit last point on reopen
(require 'saveplace)
(setq-default save-place t)
(setq save-place-file (locate-user-emacs-file "var/places"))

(require 'bookmark)
(setq bookmark-default-file (locate-user-emacs-file "var/bookmarks"))

;; display column information in mode line
(column-number-mode 1)
;; show size of the buffer
(size-indication-mode 1)
;; display time in 24 hour mode
(setq display-time-24hr-format t
      display-time-day-and-date t)
(display-time)

;; minibuffer: echo keys immediately, use ido, M-x partial command completion
(setq echo-keystrokes 0.01)
(if (fboundp 'partial-completion-mode)
    (partial-completion-mode 1)
  (setq completion-styles '(partial-completion initials)
    completion-pcm-complete-word-inserts-delimiters t))
;; ido minibuffer completion (icicles doesn't like ttys)
(if (fboundp 'ido-mode)
    (ido-mode 1))
(setq ido-save-directory-list-file (locate-user-emacs-file "var/ido.last")
      ido-enable-last-directory-history nil)
;; smex
(defadvice where-is-internal (after remove-menu-bar)
  "Don't let where-is-internal show any menu bar bindings."
  (setq ad-return-value
        (remove nil
                (mapcar (lambda (a)
                          (if (and (vectorp a)
                                   (eq (car (append a nil)) 'menu-bar))
                              nil
                            a))
                        ad-return-value))))
(ad-activate 'where-is-internal)
(when (require 'smex nil t)
  (setq smex-save-file (locate-user-emacs-file "var/smex.items"))
  (smex-initialize)
  (global-set-key [remap execute-extended-command] 'smex)
  (global-set-key (kbd "M-X") 'smex-major-mode-commands))

;; no disabled commands; one key confirmation
(setq disabled-command-function nil)
(defalias 'yes-or-no-p 'y-or-n-p)

;; don't warn about various things
(require 'warnings)
(add-to-list 'warning-suppress-types '(undo discard-info))
(add-to-list 'warning-suppress-log-types '(undo discard-info))

;;;;
;;;;;; Misc.
;;;;

(defun copy-region-to-xsel ()
  (interactive)
  (shell-command-on-region (region-beginning) (region-end) "xsel -i -b -l /dev/null")
  (deactivate-mark))
(define-key ctl-x-map "x" 'copy-region-to-xsel)

;; quick edits (C-x r j <key>)
(set-register ?e `(file . ,(locate-user-emacs-file "init.el")))
(set-register ?g `(file . ,gnus-init-file))

(defun eaw-conf-comp (string predicate action)
  (let (files)
    (dolist (file (directory-files (locate-user-emacs-file "elisp/conf")))
      (if (and (string-match-p "^ew-.*\\.el$" file)
               (eq (compare-strings string 0 (length string)
                                    (substring file 3 -3) 0 (length string)) t))
          (add-to-list 'files (substring file 3 -3))))
    files))

(defun eaw-goto-conf (file)
  (interactive (list
                (completing-read "Conf file: " 'eaw-conf-comp)))
  (let* ((list (file-expand-wildcards (locate-user-emacs-file (concat "elisp/conf/ew-" file "*.el"))))
         (full (if list (car list) (locate-user-emacs-file (concat "elisp/conf/ew-" file ".el")))))
    (find-file (file-truename full))))
(global-set-key (kbd "C-x C-c") 'eaw-goto-conf)

(defun eaw-find-file-up-heirarchy (filename &optional base)
  (let ((basedir (or (and base (directory-file-name (expand-file-name base))) "/"))
        (curdir (directory-file-name (expand-file-name default-directory))))
    (if (and (>= (length curdir) (length basedir))
             (compare-strings curdir 0 (length basedir)
                              basedir 0 (length basedir)))
        (if (file-readable-p (concat curdir "/" filename))
            (directory-file-name (expand-file-name default-directory))
          (if (not (string= curdir basedir))
              (let ((default-directory (file-name-directory curdir)))
                (eaw-find-file-up-heirarchy filename basedir)))))))

(defun eaw-find-file-down-heirarchy (filename &optional base)
  (let ((basedir (or (and base (directory-file-name (expand-file-name base))) "/"))
        (curdir (directory-file-name (expand-file-name default-directory)))
        dirlist)
    (while (and (>= (length curdir) (length basedir))
                (compare-strings curdir 0 (length basedir)
                                 basedir 0 (length basedir)))
      (add-to-list 'dirlist curdir)
      (setq curdir (directory-file-name (file-name-directory curdir))))
    (dolist (dir dirlist)
      (if (file-readable-p (concat dir "/" filename))
          (return dir)))))

(require 'htmlize nil t)
(defun eaw-htmlize-init (dir)
  (interactive "DDirectory to write html files to: ")
  (let ((init (expand-file-name "index.html" dir)))
    (htmlize-file (locate-user-emacs-file "init.el") init)
    (with-temp-buffer
      (insert-file-contents init)
      (while (re-search-forward ">\\(ew-[a-z]+\\)<" nil t)
        (let ((match (match-string 1)))
          (replace-match "><a href=\"\\1.el.html\">\\1</a><" nil nil)
          (htmlize-file
           (locate-user-emacs-file (concat "elisp/conf/" match ".el"))
           (expand-file-name (concat match ".el.html") dir))
          ;; special-case ew-gnus for gnus/rc
          (if (string= match "ew-gnus")
              (let ((gnus-html (expand-file-name (concat match ".el.html") dir)))
                (with-temp-buffer
                  (insert-file-contents gnus-html)
                  (while (re-search-forward "\\(gnus-init-file\\)" nil t)
                    (replace-match "<a href=\"gnus-init-file.html\">\\1</a>" nil nil))
                  (write-region (point-min) (point-max) gnus-html))
                (htmlize-file gnus-init-file (expand-file-name "gnus-init-file.html" dir))))))
      (write-region (point-min) (point-max) init))))

;; don't notify me when auto-reverting.
(setq auto-revert-verbose nil)

;; don't use the GUI
(defalias 'message-box 'message)
(setq use-dialog-box nil)

(if (executable-find "x-www-browser")
    (progn
      (setq browse-url-generic-program "x-www-browser")
      (setq browse-url-browser-function 'browse-url-generic)))

(setq url-show-status nil
      url-cookie-file (locate-user-emacs-file "var/cookies"))

;; idlwave files go in ~/.emacs.d/var/idlwave
(setq idlwave-config-directory (locate-user-emacs-file "var/idlwave"))

;; why isn't this the default?
(setq org-enforce-todo-dependencies t)
(setq org-special-ctrl-a/e t)
(defun eaw-org-hook ()
  (set-face-attribute 'org-document-title nil :height 'unspecified)
  (set-face-attribute 'org-column nil :height 'unspecified))
(add-hook 'org-mode-hook 'eaw-org-hook)

;; artist mode, right-click should bring up the menu
(add-hook 'artist-mode-init-hook
          (lambda ()
            (define-key artist-mode-map (kbd "<down-mouse-3>") 'artist-mouse-choose-operation)))

;; proced defaults
(setq-default proced-sort 'start
              proced-tree-flag t
              proced-descend nil)

;; tramp files in .emacs.d/var, obey PATH in .profile
(require 'tramp)
(setq tramp-persistency-file-name (locate-user-emacs-file "var/tramp"))
(add-to-list 'tramp-remote-path 'tramp-own-remote-path)

;; don't bind dired to C-x C-j
(require 'dired)
(setq dired-bind-jump nil)
;; in dired, i inserts a subdir, so I should kill the subdir...?
(add-to-list 'dired-mode-hook (lambda ()
                                (define-key dired-mode-map "I" 'dired-kill-subdir)))

;; Don't create a WoMan log buffer
(require 'woman)
(defun eaw-woman-log () nil)
(defalias 'WoMan-log-begin 'eaw-woman-log)
(defun eaw-woman-log-1 (string &optional end) nil)
(defalias 'WoMan-log-1 'eaw-woman-log-1)

(when (require 'info nil t)
  (add-to-list 'Info-directory-list "/usr/share/info")
  (add-to-list 'Info-directory-list "/usr/local/share/info"))

;; save passwords longer
(if (require 'password-cache nil t)
    (setq password-cache-expiry nil))

;; don't open symlinks, open the true file
(setq find-file-visit-truename t)

;; prompt before killing certain files
(defun eaw-kill-buffer-query-function ()
  (or (not (member major-mode '(eshell-mode svn-status-mode jabber-roster-mode)))
      (yes-or-no-p (format "Buffer `%s' is special; kill it? "
               (buffer-name (current-buffer))))))
(add-hook 'kill-buffer-query-functions 'eaw-kill-buffer-query-function)

(provide 'ew-main)