REBOL [
    Title: "Twitter"
    Date: 20-Jul-2011
    Author: "Christopher Ross-Gill"
    Version: 0.1.1
    Rights: http://creativecommons.org/licenses/by-sa/3.0/
    File: %twitter-vid.r
    Settings: [
        ; use if not working with 'do/args
        Consumer-Key: <consumer-key>
        Consumer-Secret: <consumer-secret>
        User-Store: <path-to-saved-users>
    ]
]

do http://reb4.me/r/link-up
do http://reb4.me/r/xp-styles
do/args http://reb4.me/r/twitter any [
    system/script/args
    system/script/header/settings
]

view center-face do bind [
    ui/window: layout [
        origin 0 space 0 backeffect styles/background

        panel effect styles/background bind [
            origin 20
            text: h1 "" 500x220 as-is font styles/h1 feel none styles/text-color
        ] ui

        panel effect styles/panel bind [
            origin 20x10 space 12x0

            image: image 48x48 styles/icon effect [fit]

            return
            user: h3 "" 540 font styles/h3 feel none

            guide
            link: text 200 "" actions/browse font styles/info-link

            return
            reply: text "Reply" actions/reply font styles/info-link

            return
            text "New" actions/update font styles/info-link
        ] ui
    ]

    engage
] context [
    styles: [
        edging 17.34.51
        text-color 0.17.34
        link-color 204.0.0
        icon #[image! 1x1 64#{ESIz}]
        ; background [gradient 1x1 119.119.119 68.68.68 grid 3x3 119.119.119]
        background [gradient 0x1 170.221.255 153.204.238 grid 3x3 170.221.255]
        panel [gradient 0x1 34.68.102 17.34.51]
        text [
            name: "verdana"
            size: 14
            style: 'bold
            color: 0.17.34
        ]
        info-link [
            name: "verdana"
            size: 14
            style: [bold underline]
            valign: 'middle
            color: first colors: [255.255.255 255.0.0]
        ]
        h3 [
            name: "verdana"
            size: 14
            style: 'bold
            color: white
            valign: 'middle
            shadow: 2x2
        ]
        h1 [
            name: "georgia"
            size: 26
            style: [bold italic]
            space: 0x4
        ]
        field [
            border [size: 1x1 color: styles/edging effect: []]
            colors [255.255.255 236.236.236]
        ]
        profile [
            border [size: 1x1 color: 204.204.204 effect: []]
        ]
    ]

    ui: context [
        window: text: image: user: link: reply: none
    ]

    state: context [
        user: none
        tweets: copy []
        images: copy []

        tail?: false
        head?: true
    ]

    actions: [
        browse [all [url? face/data browse face/data]]
        reply [compose-update/reply ui/reply/data]
        update [compose-update]
        next [
            unless tail? next state/tweets [
                state/tweets: next state/tweets
            ]
            redraw
        ]
        back [
            state/tweets: back state/tweets
            redraw
        ]
    ]

    redraw: use [since][
        since: func [date [date!] /local age][
            age: difference now date
            case [
                age < 0:1:0 ["Less than a minute ago"]
                age < 1:0:0 [join form age/minute " minute(s) ago"]
                age < 24:0:0 [join form age/hour " hour(s) ago"]
                age < 168:0:0 [join form round age/hour / 24 " day(s) ago"]
                age < 8548:0:0 [join form round age/hour / 168 " week(s) ago"]
            ]
        ]

        has [tweet][
            if tweet: pick state/tweets 1 [
                set-face ui/text tweet/text
                show link-up/colors ui/text styles/text-color styles/link-color
                set-face ui/image select state/images tweet/user/screen_name
                set-face ui/user tweet/user/screen_name
                set-face ui/link since tweet/created_at
                ui/link/data: rejoin [https://twitter.com/ tweet/user/screen_name %/status/ tweet/id]
                ui/reply/data: :tweet
            ]
        ]
    ]

    refresh: use [load-date load-image authenticate format][
        load-date: func [date [string!]][
            date: parse date none
            date: attempt [load rejoin [date/3 "-" date/2 "-" date/6 "/" date/4]]
        ]

        load-image: func [url [string! url!]][
            case/all [
                string? url [url: attempt [load url]]
                url? url [url: attempt [load url]]
                none? url [url: styles/icon]
                image? url [url]
            ]
        ]

        format: func [tweets [block!]][
            foreach tweet tweets [
                unless find state/images tweet/user/screen_name [
                    repend state/images [
                        tweet/user/screen_name
                        load-image tweet/user/profile_image_url_https
                    ]
                ]

                tweet/created_at: load-date tweet/created_at
            ]
        ]

        authenticate: does [
            any [
                state/user
                attempt [twitter/as state/user: ask "Work as (Twitter screen name):"]
                do [alert "Could not establish credentials." state/user: none]
            ]
        ]

        func [/page offset][
            either authenticate [
                twitter/save-users
                format state/tweets: any [attempt [twitter/home] []]
                redraw
            ][
                unview
            ]
        ]
    ]

    engage: does [
        ui/window/feel: make face/feel [
            detect: func [face event][
                unless all [
                    event/type = 'key
                    switch event/key [
                        page-up [do actions/next true]
                        page-down [do actions/back true]
                        #"^R" [do actions/reply true]
                        #"^N" [do actions/update true]
                        #"^W" [unview/all true]
                    ]
                ][
                    event
                ]
            ]
        ]

        refresh
        ui/window
    ]

    system/words/ask: use [
        request-form request response ok
    ][
        request-form: layout [
            across origin 10 space 8 backeffect styles/background

            request: h1 "" 300 font styles/text
            return

            response: field "" 300 [ok: yes hide-popup] with [flags: [return]]
            font styles/text
            edge styles/field/border
            colors styles/field/colors
            return

            ; pad 192
            btn-enter 100 [ok: yes hide-popup]
            btn-cancel 100 #"^[" [hide-popup]
        ]

        func [
            "Ask User for Input"
            question [string!] "Prompt to User"
            /hide
            /offset xy [pair!]
            /default text [string!]
        ][
            ok: no
            either hide [
                any [
                    flag-face? response 'hide
                    flag-face response 'hide
                ]
            ][
                deflag-face response 'hide
            ]

            set-face request question
            clear-face response
            set-face response copy any [text ""]
            focus response
            ctx-text/hilight-all response

            either offset [inform/offset request-form xy][inform request-form]
            all [ok either hide [response/data][get-face response]]
        ]
    ]

    compose-update: use [
        request-form request response ok
    ][
        request-form: layout [
            across origin 10 space 8 backeffect styles/background

            request: h1 "What's happening?" 300 font styles/text
            return

            response: area "" 300x200 wrap
            font styles/text
            edge styles/field/border
            colors styles/field/colors
            return

            btn-enter 100 [ok: yes hide-popup]
            btn-cancel 100 #"^[" [hide-popup]
        ]

        func [
            "Compose a Tweet"
            /reply tweet [object! none!]
            /offset xy [pair!]
        ][
            ok: no

            set-face request either reply [rejoin ["Reply to @" tweet/user/screen_name]]["What's happening?"]
            set-face response copy either reply [rejoin ["@" tweet/user/screen_name " "]][""]
            focus response
            ctx-text/unlight-text
            either offset [inform/offset request-form xy][inform request-form]

            tweet_public: get-face response
            all [
                ok
                tweet: either reply [
                    twitter/update/reply get-face response tweet/id
                ][
                    twitter/update get-face response
                ]
            ]
        ]
    ]
]