/*
 * XML.nsh (16.07.2019)
 *
 * Author: LegendaryHawk
 *
 * Description:
 * Basic codes for handling XML files in "portable apps"
 *
 * Usage:
 * ${ReadXMLText} FILE.xml "/PATH/TO/SETTING" $var
 * ${WriteXMLText} FILE.xml "/PATH/TO/SETTING" "String to write" $var
 * ${ReadXMLAttribute} FILE.xml "/PATH/TO/SETTING" "ATTRIBUTE" $var
 * ${WriteXMLAttribute} FILE.xml "/PATH/TO/SETTING" "ATTRIBUTE" "String to write" $var
 *
 * Example:
 * ${ReadXMLText} $EXEDIR\myconfig.xml "/General/Settings/Language" $0
 * ${WriteXMLText} $EXEDIR\myconfig.xml "/General/Settings/Language" "German" $0
 * ${ReadXMLAttribute} $EXEDIR\myconfig.xml "/General/Settings" "Language" $0
 * ${WriteXMLAttribute} $EXEDIR\myconfig.xml "/General/Settings" "Language" "German" $0
 */

!ifndef XML_NSH_INCLUDED
!define XML_NSH_INCLUDED

; --- Includes
!include LogicLib.nsh
!include Util.nsh

!macro ReadXMLTextCall _FILE _XPATH _OUTVAR
    !verbose push
    !verbose 3
    Push `${_XPATH}`
    Push `${_FILE}`
    ${CallArtificialFunction} ReadXMLText_
    Pop `${_OUTVAR}`
    !verbose pop
!macroend
!define ReadXMLText "!insertmacro ReadXMLTextCall"

!macro WriteXMLTextCall _FILE _XPATH _STRINGTOWRITE _OUTVAR
    !verbose push
    !verbose 3
    Push `${_STRINGTOWRITE}`
    Push `${_XPATH}`
    Push `${_FILE}`
    ${CallArtificialFunction} WriteXMLText_
    Pop `${_OUTVAR}`
    !verbose pop
!macroend
!define WriteXMLText "!insertmacro WriteXMLTextCall"

!macro ReadXMLAttributeCall _FILE _XPATH _ATTRIBUTE _OUTVAR
    !verbose push
    !verbose 3
    Push `${_ATTRIBUTE}`
    Push `${_XPATH}`
    Push `${_FILE}`
    ${CallArtificialFunction} ReadXMLAttribute_
    Pop `${_OUTVAR}`
    !verbose pop
!macroend
!define ReadXMLAttribute "!insertmacro ReadXMLAttributeCall"

!macro WriteXMLAttributeCall _FILE _XPATH _ATTRIBUTE _STRINGTOWRITE _OUTVAR
    !verbose push
    !verbose 3
    Push `${_STRINGTOWRITE}`
    Push `${_ATTRIBUTE}`
    Push `${_XPATH}`
    Push `${_FILE}`
    ${CallArtificialFunction} WriteXMLAttribute_
    Pop `${_OUTVAR}`
    !verbose pop
!macroend
!define WriteXMLAttribute "!insertmacro WriteXMLAttributeCall"



!macro ReadXMLText_
    !verbose push
    !verbose 3

    ; Prepare Stack
    Exch $4 ; _FILE
    Exch
    Exch $5 ; _XPATH
    Push $0
    Push $1
    Push $2
    Push $3
    Push $R0

    ; Set default
    StrCpy $R0 error

    nsisXML::create
    nsisXML::load $4
    ${If} $0 <> 0
        nsisXML::select $5
        ${If} $2 <> 0
            nsisXML::getText
            ${If} $3 == ""
                StrCpy $R0 error-empty
            ${Else}
                StrCpy $R0 $3
            ${EndIf}

            ; Unload reference
            nsisXML::release $2
        ${Else}
            StrCpy $R0 node-not-found
        ${EndIf}
        ; Unload reference
        nsisXML::release $0
    ${EndIf}

    ; Copy output to $4
    StrCpy $4 $R0

    ; Restore Stack
    Pop $R0
    Pop $3
    Pop $2
    Pop $1
    Pop $0
    Pop $5
    Exch $4

    !verbose pop
!macroend

!macro WriteXMLText_
    !verbose push
    !verbose 3

    ; Prepare Stack
    Exch $4 ; _FILE
    Exch
    Exch $5 ; _XPATH
    Exch
    Exch 2
    Exch $6 ; _STRINGTOWRITE
    Push $0
    Push $1
    Push $2
    Push $R0

    ; Set default
    StrCpy $R0 error

    nsisXML::create
    nsisXML::load $4
    ${If} $0 <> 0
        nsisXML::select $5
        ${If} $2 <> 0
            nsisXML::setText $6
            nsisXML::save $4
            StrCpy $R0 success

            ; Unload reference
            nsisXML::release $2
        ${Else}
            StrCpy $R0 node-not-found
        ${EndIf}
        ; Unload reference
        nsisXML::release $0
    ${EndIf}

    ; Copy output to $4
    StrCpy $4 $R0

    ; Restore Stack
    Pop $R0
    Pop $2
    Pop $1
    Pop $0
    Pop $6
    Pop $5
    Exch $4

    !verbose pop
!macroend

!macro ReadXMLAttribute_
    !verbose push
    !verbose 3

    ; Prepare Stack
    Exch $4 ; _FILE
    Exch
    Exch $5 ; _XPATH
    Exch
    Exch 2
    Exch $6 ; _ATTRIBUTE
    Push $0
    Push $1
    Push $2
    Push $3
    Push $R0

    ; Set default
    StrCpy $R0 error

    nsisXML::create
    nsisXML::load $4
    ${If} $0 <> 0
        nsisXML::select $5
        ${If} $2 <> 0
            nsisXML::getAttribute $6
            ${If} $3 == ""
                StrCpy $R0 error-empty
            ${Else}
                StrCpy $R0 $3
            ${EndIf}

            ; Unload reference
            nsisXML::release $2
        ${Else}
            StrCpy $R0 node-not-found
        ${EndIf}
        ; Unload reference
        nsisXML::release $0
    ${EndIf}

    ; Copy output to $4
    StrCpy $4 $R0

    ; Restore Stack
    Pop $R0
    Pop $3
    Pop $2
    Pop $1
    Pop $0
    Pop $6
    Pop $5
    Exch $4

    !verbose pop
!macroend

!macro WriteXMLAttribute_
    !verbose push
    !verbose 3

    ; Prepare Stack
    Exch $4 ; _FILE
    Exch
    Exch $5 ; _XPATH
    Exch
    Exch 2
    Exch $6 ; _ATTRIBUTE
    Exch
    Exch 2
    Exch 3
    Exch $7 ; _STRINGTOWRITE
    Push $0
    Push $1
    Push $2
    Push $R0

    ; Set default
    StrCpy $R0 error

    nsisXML::create
    nsisXML::load $4
    ${If} $0 <> 0
        nsisXML::select $5
        ${If} $2 <> 0
            nsisXML::setAttribute $6 $7
            nsisXML::save $4
            StrCpy $R0 success

            ; Unload reference
            nsisXML::release $2
        ${Else}
            StrCpy $R0 node-not-found
        ${EndIf}
        ; Unload reference
        nsisXML::release $0
    ${EndIf}

    ; Copy output to $4
    StrCpy $4 $R0

    ; Restore Stack
    Pop $R0
    Pop $2
    Pop $1
    Pop $0
    Pop $7
    Pop $6
    Pop $5
    Exch $4

    !verbose pop
!macroend
!endif ; XML_NSH_INCLUDED
