;;
;; Convierte bloques dinámicos (en su estado actual de visibilidad) a bloques estáticos
;;
;; Rutina: UnDynamic por MP Seagull - 26 de marzo de 2010
;; 
;; MODIFICADO POR Lanny Schiele (alias 'HatchMaker Maker') - 27 de octubre de 2017
;;
;; Modificado por Sergio Manes (arqMANES) - 21 de mayo de 2025
;;

(defun c:UnDynamicFixed
    (   /
        _DefGetString
        _get_item
        _right
        _make_key
        _dynamic->static_block
        _get_dynamic_inserts_from_pickset
        _safe_convert
        _main
    )

    (vl-load-com)

    ;; Función para obtener string con default
    (defun _DefGetString (prmpt default allowspace / d2 ans)
        (if allowspace
            (setq ans
                (cond
                    ((not (= (setq d2 (getstring T (strcat prmpt " <" default ">: "))) ""))
                     d2)
                    (default)
                )
            )
            (setq ans
                (cond
                    ((not (= (setq d2 (getstring (strcat prmpt " <" default ">: "))) ""))
                     d2)
                    (default)
                )
            )
        )
        ans
    )

    ;; Obtener item de colección de forma segura
    (defun _get_item ( collection key / item result )
        (setq result
            (vl-catch-all-apply
                '(lambda ( ) (setq item (vla-item collection key)))
            )
        )
        (if (vl-catch-all-error-p result)
            nil
            item
        )
    )

    ;; Obtener substring derecho
    (defun _right ( str n / len )
        (if (< n (setq len (strlen str)))
            (substr str (1+ (- len n)))
            str
        )
    )

    ;; Crear nombre único para el bloque
    (defun _make_key ( collection prefix len / key i pad )
        (setq i 0)
        (setq pad "")
        (while (< (strlen pad) len)
            (setq pad (strcat "0" pad))
        )
        (while
            (_get_item collection
                (setq key
                    (strcat prefix
                        (_right
                            (strcat pad (itoa (setq i (1+ i))))
                            len
                        )
                    )
                )
            )
        )
        key
    )

    ;; Conversión segura de bloque dinámico a estático
    (defun _safe_convert ( insert new_name / result )
        (setq result
            (vl-catch-all-apply
                '(lambda ()
                    ;; Verificar que el objeto sea válido
                    (if (and insert
                             (not (vlax-object-released-p insert))
                             (vlax-property-available-p insert 'IsDynamicBlock)
                             (eq :vlax-true (vla-get-isdynamicblock insert)))
                        (progn
                            (vla-ConvertToStaticBlock insert new_name)
                            T
                        )
                        nil
                    )
                )
            )
        )
        (not (vl-catch-all-error-p result))
    )

    ;; Función principal de conversión
    (defun _dynamic->static_block ( blocks insert len prefix / new_name )
        (if (setq new_name (_make_key blocks prefix len))
            (if (_safe_convert insert new_name)
                new_name
                nil
            )
            nil
        )
    )

    ;; Obtener bloques dinámicos de selección
    (defun _get_dynamic_inserts_from_pickset ( ss / i object inserts obj_name )
        (setq inserts '())
        (if ss
            (progn
                (setq i 0)
                (while (< i (sslength ss))
                    (if (setq object (vlax-ename->vla-object (ssname ss i)))
                        (progn
                            ;; Verificar de forma segura
                            (setq obj_name
                                (vl-catch-all-apply
                                    '(lambda () (vla-get-objectname object))
                                )
                            )
                            (if (and (not (vl-catch-all-error-p obj_name))
                                     (eq "AcDbBlockReference" obj_name))
                                ;; Verificar si es dinámico de forma segura
                                (if (vl-catch-all-apply
                                        '(lambda ()
                                            (eq :vlax-true (vla-get-isdynamicblock object))
                                        )
                                    )
                                    (setq inserts (cons object inserts))
                                )
                            )
                        )
                    )
                    (setq i (1+ i))
                )
            )
        )
        inserts
    )

    ;; Función principal
    (defun _main ( document / blocks inserts prefix len converted failed ss )
        ;; Inicializar variables
        (setq converted 0 failed 0)
        
        ;; Obtener colección de bloques
        (setq blocks (vla-get-blocks document))
        
        ;; Solicitar selección
        (princ "\nSeleccione los bloques dinámicos a convertir:")
        (if (setq ss (ssget ":L" (list (cons 0 "INSERT"))))
            (progn
                ;; Filtrar solo bloques dinámicos
                (setq inserts (_get_dynamic_inserts_from_pickset ss))
                
                (if inserts
                    (progn
                        (princ (strcat "\nSe encontraron " (itoa (length inserts)) " bloques dinámicos."))
                        
                        ;; Obtener prefijo
                        (if (not *UnDynamic:Prefix*)
                            (setq *UnDynamic:Prefix* "STATIC_")
                        )
                        (setq prefix (_DefGetString "\nPrefijo para bloques estáticos" *UnDynamic:Prefix* T))
                        (setq *UnDynamic:Prefix* prefix)
                        
                        ;; Longitud fija para numeración
                        (setq len 6)
                        
                        ;; Procesar conversiones
                        (princ "\nConvirtiendo bloques...")
                        (foreach insert inserts
                            (princ ".")
                            (if (_dynamic->static_block blocks insert len prefix)
                                (setq converted (1+ converted))
                                (setq failed (1+ failed))
                            )
                        )
                        
                        ;; Mostrar resultados
                        (princ (strcat "\nConversión completada."))
                        (princ (strcat "\nBloques convertidos: " (itoa converted)))
                        (if (> failed 0)
                            (princ (strcat "\nConversiones fallidas: " (itoa failed)))
                        )
                    )
                    (princ "\nNo se encontraron bloques dinámicos en la selección.")
                )
            )
            (princ "\nSelección cancelada.")
        )
        (princ)
    )

    ;; Ejecutar
    (_main (vla-get-activedocument (vlax-get-acad-object)))
)