;;; SPIS_RUN_SETS.lsp
;;; SPISRUNSETS — запускает сборку комплекта дисциплин из AutoCAD.
;;;
;;; Команда НЕ создаёт файлы сама: операции с документами (создать,
;;; открыть, сохранить) из LISP блокируют AutoCAD — проверено на
;;; AutoCAD 2020: vla-Open, _.OPEN и _.SAVEAS внутри LISP вешают сессию.
;;;
;;; Поэтому команда запускает ВНЕШНИЙ Python-скрипт, который работает
;;; с AutoCAD через COM. AutoCAD остаётся свободен.
;;;
;;; Что создаётся (схема согласована):
;;;   ЭТР = АР + СС + ВК + ОВ
;;;   СС  = АР + ВК + ОВ + ЭТР
;;;   ВК  = АР + СС + ОВ + ЭТР
;;;   ОВ  = АР + СС + ВК + ЭТР
;;;   АР  — основа, сама ничего не подключает
;;;
;;; ЗАПУСК идёт через run_sets_launcher.py: он создаёт bat-файл в
;;; OEM-кодировке (cp866) и стартует сборку скрыто. AutoLISP так не
;;; умеет — (open ... "w") пишет в системной кодировке, и русские
;;; пути в bat бьются.

(vl-load-com)

;; Папка с инструментами СПИС (пути всегда с обратным слэшем).
(defun srs:tools-dir (/ f r)
  (cond
    ;; 1) файл найден в путях поддержки
    ((setq f (findfile "SPIS_RUN_SETS.lsp"))
      (vl-string-translate "/" "\\" (vl-filename-directory f)))
    ;; 2) папка, запомненная загрузчиком SPIS_TOOLS / командой SPISSETDIR
    ((and (setq r (vl-catch-all-apply 'vl-registry-read
                     (list "HKEY_CURRENT_USER\\Software\\GENPRO\\SPIS" "ToolsDir")))
          (not (vl-catch-all-error-p r)) r (> (strlen r) 0))
      (vl-string-translate "/" "\\" r))
    ;; 3) глобальная переменная, выставленная загрузчиком
    ((and *SPIS-DIR* (> (strlen *SPIS-DIR*) 0))
      (vl-string-translate "/" "\\" *SPIS-DIR*))
    ;; 4) загрузчик рядом
    ((setq f (findfile "SPIS_TOOLS.lsp"))
      (vl-string-translate "/" "\\" (vl-filename-directory f)))
    ;; 5) аварийный вариант
    (T "G:\\Мой диск\\lisp-code\\SPIS")
  )
)

;; Интерпретатор Python: берём из локального окружения рядом со скриптами.
;; Предпочитаем pythonw.exe — он не создаёт консольного окна.
(defun srs:python (/ tools local)
  (setq tools (srs:tools-dir))
  (setq local (strcat (vl-string-right-trim "\\/" tools) "\\.venv\\Scripts\\pythonw.exe"))
  (if (findfile local)
    local
    (progn
      (setq local (strcat (vl-string-right-trim "\\/" tools) "\\.venv\\Scripts\\python.exe"))
      (if (findfile local) local "python")
    )
  )
)

(defun srs:norm (p)
  (vl-string-right-trim "\\" (vl-string-translate "/" "\\" p))
)

(defun srs:split (str sep / pos res)
  (setq res nil)
  (while (setq pos (vl-string-search sep str))
    (setq res (cons (substr str 1 pos) res)
          str (substr str (+ pos 1 (strlen sep))))
  )
  (reverse (cons str res))
)

;; Корпус для имён файлов дисциплин.
;; "АР К9.dwg"          -> "К9"           (корпус в имени файла)
;; "АР.dwg" в "Ларус"   -> "Ларус"        (имя файла без корпуса — берём папку)
(defun srs:corpus (root / dir files base parts parent)
  (setq dir (srs:norm (strcat (srs:norm root) "\\АР")))
  (if (vl-file-directory-p dir)
    (setq files (vl-directory-files dir "*.dwg" 1))
  )
  (if files
    (progn
      (setq base (vl-filename-base (car files)))
      (setq parts (srs:split base " "))
      (if (> (length parts) 1)
        ;; имя из нескольких слов: корпус — последнее слово
        (last parts)
        ;; имя из одного слова: значит корпус в названии папки
        (progn
          (setq parent (vl-filename-base (srs:norm root)))
          (if (or (not parent) (= parent "")) base parent)
        )
      )
    )
    nil
  )
)

;; Основная команда -------------------------------------------------
(defun c:SPISRUNSETS (/ root corpus tools launcher vpython shell cmd real-res)
  (setq root (srs:norm (getstring T "\nКорень проекта (папки АР, ЭТР, СС, ВК, ОВ): ")))
  (cond
    ((not (vl-file-directory-p root))
      (prompt (strcat "\nПапка не найдена: " root))
    )
    ((not (setq corpus (srs:corpus root)))
      (prompt "\nВ папке АР нет файлов DWG — не определить корпус.")
    )
    (T
      (setq tools (srs:tools-dir))
      (setq launcher (strcat tools "/run_sets_launcher.py"))
      (cond
        ((not (findfile launcher))
          (prompt (strcat "\nНе найден файл запуска: " launcher))
          (prompt "\nОн должен лежать рядом с этим LISP-файлом.")
        )
        (T
          (prompt (strcat "\nКорень: " root))
          (prompt (strcat "\nКорпус: " corpus))
          (prompt "\nСхема:  каждый раздел = АР + смежные дисциплины")
          (initget "Yes No")
          (cond
            ((/= (getkword "\nСоздать комплект? [Yes/No] <No>: ") "Yes")
              (prompt "\nОтменено. Ничего не изменено.")
            )
            (T
              (setq vpython (srs:python))
              ;; Диагностика: пути
              (prompt (strcat "\n[отладка] python:  " vpython))
              (prompt (strcat "\n[отладка] скрипт:  " launcher))
              (prompt (strcat "\n[отладка] root:    " root))
              (prompt (strcat "\n[отладка] corpus:  " corpus))
              ;; Запуск через WScript.Shell.Run — startapp в AutoCAD 2020
              ;; не работает (возвращает NIL даже для cmd.exe).
              (setq shell (vl-catch-all-apply 'vlax-create-object (list "WScript.Shell")))
              (if (vl-catch-all-error-p shell)
                (prompt (strcat "\n[отладка] WScript.Shell: ошибка " (vl-catch-all-error-message shell)))
                (progn
                  (prompt "\n[отладка] WScript.Shell: объект создан")
                  (setq cmd (strcat "\"" vpython "\" \"" launcher "\" \""
                                    root "\" \"" corpus "\""))
                  (prompt (strcat "\n[отладка] команда: " cmd))
                  (setq real-res (vl-catch-all-apply 'vlax-invoke
                    (list shell "Run" cmd 0 0)))
                  (if (vl-catch-all-error-p real-res)
                    (prompt (strcat "\n[отладка] ошибка Run: " (vl-catch-all-error-message real-res)))
                    (prompt (strcat "\n[отладка] Run: OK, код=" (vl-princ-to-string real-res)))
                  )
                  (vlax-release-object shell)
                )
              )
              (prompt "\n=== Запущено в фоне ===")
              (prompt (strcat "\nХод выполнения: " (getenv "TEMP") "\\spis_sets_log.txt"))
              (prompt "\nAutoCAD свободен — сборка идёт отдельно.")
              (prompt "\nКогда файлы появятся, выполните SPISATTACHSETS в СПИС.")
            )
          )
        )
      )
    )
  )
  (princ)
)

(prompt "\nSPIS_RUN_SETS загружен. Команда: SPISRUNSETS")
(princ)
