module progress
implicit none

private

public :: progresswindow, initprogress

    type progresswindow

        integer::win
        integer::cancel
        
        character(128)::text
        
        contains
        
        procedure :: close => closeprogress
        procedure :: draw  => drawprogress
        
    end type progresswindow

    interface initprogress
        module procedure::initprogress_simple, initprogress_with_cancel
    end interface initprogress

contains

    ! Creates a new progress window
    function initprogress_simple(title, text) result(p)
    use appgraphics
    implicit none
    
        type(progresswindow), volatile::p
        character(*), intent(in)::title
        character(*), intent(in), optional::text

        p%win = initwindow(400, 100, title=title, dbflag=.FALSE., closeflag=.FALSE.)
        call setbkcolor(systemcolor(COLOR_WINDOW_BKGD))
        call setcolor(BLACK)
        call settextstyle(WINDOWS_FONT, HORIZ_DIR, 10)
        call setfillstyle(SOLID_FILL, RED)
        p%cancel = -1
        
        if(present(text)) then
            p%text = text
        else
            p%text = "Standby..."
        end if
        
        call drawprogress(p, 0)
    
    end function initprogress_simple

    function initprogress_with_cancel(title, cancelsub, text) result(p)
    use appgraphics
    implicit none
    
        type(progresswindow), volatile::p
        character(*), intent(in)::title
        interface
            subroutine cancelsub
            end subroutine cancelsub
        end interface
        character(*), intent(in), optional::text
        
        if(present(text)) then
            p = initprogress_simple(title, text=text)
        else
            p = initprogress_simple(title)
        end if
        
        p%cancel = createbutton(345, 70, 50, 25, "Cancel", cancelsub)
        
    end function initprogress_with_cancel

    ! Closes our progress window
    subroutine closeprogress(p)
    use appgraphics
    implicit none
    
    class(progresswindow), volatile::p
    
        call closewindow(p%win)
        
    end subroutine closeprogress
        
    subroutine drawprogress(p, completed, text)
    use appgraphics
    implicit none
    
        class(progresswindow), volatile::p
        integer, intent(in)::completed
        character(*), intent(in), optional::text
        
        integer::progress_total
        integer::progress_completed
        
        if(present(text)) then
            p%text = text
        end if

        call setcurrentwindow(p%win)
        call clearviewport()
        
        if(len_trim(p%text) > 0) then
            call outtextxy(5, 5, trim(p%text))
        end if
        
        progress_total = getmaxx() - 10
        
        ! Below we'll draw a simple box, unfilled
        call moveto(5, 25)
        call lineto(progress_total+5, 25)
        call lineto(progress_total+5, 50)
        call lineto(5, 50)
        call lineto(5, 25)
        
        ! Bounds-check our completed value
        progress_completed = progress_total*completed/100
        if(progress_completed > progress_total) then
            progress_completed = progress_total
        elseif(progress_completed < 0) then
            progress_completed = 0
        end if
        
        ! Now we can fill a bar
        call bar(5, 25, progress_completed+5, 50)
        
    end subroutine drawprogress
    
end module progress