### ----------------------------------------------------
### -- IUP
### -- Licenses: Artistic-2.0
### -- Authors: Henrique Dias, Tobias Leich, David Warring, Zoffix Znet, Naoum Hankache, Robert Ransbottom, Günter Milder
### -- File: lib/IUP.rakumod
### ----------------------------------------------------
### -- Chunk 2 of 2
 &?ROUTINE.name));
        IupGetHandle($name )
    }

    method set-handle(Str $name -->Ihdle) { IupSetHandle($name, self) }
    method set_handle(Str $name -->Ihdle) {
        DEPRECATED('set-handle','0.5.0','1.0.0', :what( &?ROUTINE.name));
        IupSetHandle($name, self)
    }

    ###
    # getallnames getalldialogs getname
    method set-attr-handle(Str $name, Ihdle $ih_named -->Mu) {
        IupSetAttributeHandle(self, $name, $ih_named);
    }
    method set-attribute-handle(Str $name, Ihdle $ih_named -->Mu) {
        DEPRECATED('set-attr-handle','0.5.0','1.0.0',
                :what( &?ROUTINE.name));
        IupSetAttributeHandle(self, $name, $ih_named);
    }
    method set_attribute_handle(Str $name, Ihdle $ih_named -->Mu) {
        DEPRECATED('set-attr-handle','0.5.0','1.0.0',
                :what( &?ROUTINE.name));
        IupSetAttributeHandle(self, $name, $ih_named);
    }

    ###
    # getattributehandle
    # setattributehandleid getattributehandleid setattributehandleid2
    # getattributehandleid2 getclassname getclasstype getallclasses
    # getclassattributes getclasscallbacks saveclassattributes
    # setclassdefaultattribute classmatch create createp createv
    method fill(-->Ihdle) { IupFill() }

    method radio( Ihdle $child -->Ihdle) { IupRadio($child) }

    # space

    method !allocator(@child -->CArray[Pointer]) {
        our $pts = CArray[Pointer].allocate(@child.elems + 1);
         my $i = 0;
         for @child -> $elem {
            $pts[$i++] = $elem;
         }
         $pts;
    }

    method vbox(*@child -->Ihdle) {
        IupVboxv(self!allocator(@child));
    }

    method zbox(*@child -->Ihdle) {
        IupZboxv(self!allocator(@child));
    }

    method hbox(*@child -->Ihdle) { IupHboxv(self!allocator(@child)) }

    # normalizer, cbox,

    method sbox( Ihdle $child -->Ihdle) { IupSbox($child) }

    # split,scrollbox, flatscrollbox

    method gridbox(*@child --> Ihdle) { IupGridBoxv(self!allocator(@child)) }

    method multibox(*@child -->Ihdle) { IupMultiBoxv(self!allocator(@child)) }

    method expander( $child -->Ihdle){  IupExpander( $child) }

    # detachbox

    method backgroundbox(Ihdle $child -->Ihdle) { IupBackgroundBox $child }

    method frame($child -->Ihdle) { IupFrame($child); }

    # FlatFrame
    ###

    method image(
        Int $width where $width > 0,
        Int $height where $height > 0,
        $pixels,
        Int $color_space where 0..IUP_RGBA = 0 -->Ihdle) {

        given $color_space {
            when IUP_RGB { return IupImageRGB($width, $height, $pixels); }
            when IUP_RGBA { return IupImageRGBA($width, $height, $pixels); }
            default { return IupImage($width, $height, $pixels); }
        }
    }

    ###

    method item(Str $title, Str $action = '' -->Ihdle) {
        IupItem($title, $action)
    }
    method submenu(Str $title, $child -->Ihdle) { IupSubmenu($title, $child) }

    method separator(-->Ihdle) { IupSeparator }

    method menu(*@child -->Ihdle) { IupMenuv(self!allocator(@child)) }

    ###

    method button(Str $title, Str $action = "" -->Ihdle) {
        IupButton($title, $action);
    }

    # FlatButton FlatToggle DropButton FlatLabel FlatSeparator

    method canvas(Str $action -->Ihdle) { IupCanvas($action) }

    method dialog($child -->Ihdle) { IupDialog($child) }

    method user(-->Ihdle) { IupUser() }

    # thread

    method label(Str $str = '' -->Ihdle) { IupLabel($str) }

    method list(Str $action = Str -->Ihdle) { IupList( $action) }

    method matrix(Str $action = '' --> Ihdle) { IupMatrix($action) }

     method matrixlist(--> Ihdle) {IupMatrixList()}

    # flatlist

    method text(Str $action = '' -->Ihdle) { IupText($action) }

    method multiline(Str $action = '' -->Ihdle) { IupMultiLine($action) }

    method toggle(Str $title, Str $action = Str -->Ihdle) {
        IupToggle( $title, $action)
    }

    # Timer Clipboard ProgressBar

    # Make a slider to select a value in a limited range. AKA scale.
    method val(Str $type --> Ihdle) { IupVal($type) }

    # FlatVal FlatTree
    # Tabs Tabsv FlatTabs FlatTabsv Tree Link AnimatedLabel
    # DatePick Calendar Colorbar Gauge

    method dial(Str $type -->Ihdle) { IupDial($type) }

    # ColorBrowser Spin Spinbox StringCompare SaveImageAsText ImageGetHandle
    # TextConvertLinColToPos TextConvertPosToLinCol ConvertXYToPos StoreGlobal

    ###
    # StoreAttribute SetfAttribute StoreAttributeId SetfAttributeId
    # StoreAttributeId2 SetfAttributeId2 TreeSetUserId TreeGetUserId
    # TreeGetId TreeSetAttributeHandle

    method file-dlg(-->Ihdle)    { IupFileDlg      }

    method message-dlg(-->Ihdle) { IupMessageDlg   }

    method color-dlg(-->Ihdle)    { IupColorDlg    }

    method font-dlg(-->Ihdle)     { IupFontDlg     }

    method progress-dlg(-->Ihdle) { IupProgressDlg }

    method get-file(Str $arg -->int32) {
        IupGetFile($arg);
    }

    method message(Str $title, Str $message -->Mu) {
        IupMessage($title, $message)
    }

    # Messagef MessageError MessageAlarm

    method alarm( Str:D $title, Str:D $msg,
            Str:D $b1txt, Str $b2txt, Str $b3txt -->int32) {
        IupAlarm( $title, $msg, $b1txt, $b2txt, $b3txt );
    }

    # IupScanf

    # .list-dialog
    #
    # NOTE: pre-selects/highlights are by indices for both multis.  Upstream
    #       the Clang single selection version used origin one.  That behavior
    # behavior can be got by calling the _native_ IupListDialog directly.
    #
    # $presel versus @presel distinguishes which multi is called.
    # For simple single selection, Int or 0 yield the default preselect.
    # For the multiple selection, use the empty array to get no preselection.

    multi method list-dialog( Str:D $title, Array[Str] $list, Int $presel,
            Int:D $max_col, Int:D $max_lin -->Array) {
               say "in list-dialog single" if $*DEBUG;
        IupListDialog $title, $list, $presel, $max_col, $max_lin;
    }

    multi method list-dialog( Str:D $title, Array[Str] $list, Int @presel,
            Int:D $max_col, Int:D $max_lin -->Array) {
                say "in list-dialog multi" if $*DEBUG;
        IupListDialog $title, $list, @presel, $max_col, $max_lin;
    }

    method classmatch(Str $classname --> Bool) {
        return IupClassMatch(self, $classname) ?? True !! False;
    }

    method get-classname(--> Str) { return IupGetClassName(self); }


    # GetText GetColor GetParam GetParamv Param ParamBox ParamBoxv LayoutDialog
    # ElementPropertiesDialog GlobalsDialog ClassInfoDialog
}

class IUP:ver<0.5.6> is IUP::Handle {

    constant Ihdle = IUP::Handle;
    constant Ptr = Pointer;

    # Must be called before any other IUP function.
    sub IupOpen(int32 is rw, Pointer[CArray[Str]] is rw -->int32)
            is native(IUP_LIB) {*};

    # Ends IUP usage releasing memory. It destroys all named dialogs & elems.
    sub IupClose() is native(IUP_LIB) {*};

    sub IupControlsOpen() is native(IUPCONTROLS_LIB) {*}

    # IupIsOpened

    sub IupImageLibOpen() is native(IUPIMG_LIB) {*};

    # Starts loop on interaction that stops when a callback returns IUP_CLOSE,
    # IupExitLoop is called, or all dialogs are hidden.
    sub IupMainLoop( -->int32) is native(IUP_LIB) {*};

    # IupLoopStep IupLoopStepWait IupMainLoopLevel
    # IupFlush IupExitLoop
    # IupPostMessage  IupRecordInput  IupPlayInput   IupUpdate
    # IupUpdateChildren IupRedraw IupRefreshChildren
    # IupExecute IupExecuteWait IupHelp IupLog
    # IupLoad    IupLoadBuffer

    ###

    # Return version string
    sub IupVersion(-->str) is export is native(IUP_LIB) {*}

    # Return version's date.
    sub IupVersionDate(-->Str) is native(IUP_LIB) is export {*}

    # Return version number.
    sub IupVersionNumber(-->int32) is export is native(IUP_LIB) {*}

    # IupVersionShow

    # Sets the user language: English, Portuguese or Spanish
    sub IupSetLanguage(Str) is native(IUP_LIB) {*};

    # Gets the user language.
    sub IupGetLanguage( -->Str) is native(IUP_LIB) {*};

    # IupSetLanguageString IupStoreLanguageString IupGetLanguageString
    # IupSetLanguagePack


    ### METHODS ###

    method open(@argv = [] --> int32) {
        my int32 $argc = @argv.elems;
        my CArray[Str] $arglist = CArray[Str].new();
        my Pointer $ptr;
        my UInt $i = 0;

        for @argv -> $a {
            $arglist[$i] = $a.Str;
            $i++;
        }
        $ptr = nativecast(Pointer[CArray[Str]], $arglist);
        IupOpen($argc, $ptr);
    }

    method controls-open(-->Mu) { IupControlsOpen(); }

    method close(-->Mu) { IupClose }

    method image-lib-open(-->Mu) { IupImageLibOpen }
    method image_lib_open(-->Mu) {
        DEPRECATED('image-lib-open','0.5.0','1.0.0', :what( &?ROUTINE.name));
        IupImageLibOpen
    }

    method main-loop(-->int32) { IupMainLoop }
    method main_loop(-->int32) {
        DEPRECATED('main-loop','0.5.0','1.0.0', :what( &?ROUTINE.name));
        IupMainLoop
    }

#   method loop_step(Bool $wait = False -->Mu) {
#       return $wait ?? IupLoopStepWait() !! IupLoopStep();
#   }

#   method main_loop_level(-->int32) { IupMainLoopLevel }
#   method flush(-->Mu) { IupFlush }
#   method exit_loop(-->Mu) { IupExitLoop }

    ###

    method set-language(Str $language) { IupSetLanguage($language) }
    method set_language(Str $language) {
        DEPRECATED('set-language','0.5.0','1.0.0', :what( &?ROUTINE.name));
        IupSetLanguage($language)
    }

    method get-language( -->Str) { IupGetLanguage }
    method get_language( -->Str) {
        DEPRECATED('get-language','0.5.0','1.0.0', :what( &?ROUTINE.name));
        IupGetLanguage
    }

    method version(-->Str) { IupVersion }
    method get-version(-->Str) { IupVersion }
    method get_version(-->Str) {
        DEPRECATED('get-version','0.5.0','1.0.0', :what( &?ROUTINE.name));
        IupVersion
    }

    # Return version's date.
    method get-version-date(-->Str) { IupVersionDate }
    method get_version_date(-->Str) {
        DEPRECATED('get-version-date','0.5.0','1.0.0', :what( &?ROUTINE.name));
        IupVersionDate
    }

    # Return version number.
    method get-version-number(-->int32) { IupVersionNumber }
    method get_version_number(-->int32) {
        DEPRECATED('get-version-number','0.5.0','1.0.0',
                :what( &?ROUTINE.name));
        IupVersionNumber
    }
}



