main :: IO ()
main = do
    _ <- initGUI
    -- Create the builder, and load the UI file
    builder <- builderNew
    builderAddFromString builder ($(embedStringFile "src-exe/calc.glade") :: String)

    mainLabel <- builderGetObject builder castToLabel "labelBig"
    sideLabel <- builderGetObject builder castToLabel "labelSmall"

    -- Fix UTF-8 sqrt symbol
    sqrtButton <- builderGetObject builder castToButton "buttonSqrt"
    mChild <- binGetChild sqrtButton
    case mChild of
        Just child -> labelSetText (castToLabel child) "√x"
        Nothing -> return ()

    -- Color EventBoxes (= workaround for button colors)
    delBox <- builderGetObject builder castToEventBox "boxDel"
    widgetModifyBg delBox StateNormal (Color 59624 8824 8995)
    widgetModifyBg delBox StatePrelight (Color 59624 8824 8995)
    widgetModifyBg delBox StateActive (Color 59624 8824 8995)
    clrBox <- builderGetObject builder castToEventBox "boxClr"
    widgetModifyBg clrBox StateNormal (Color 59624 8824 8995)
    widgetModifyBg clrBox StatePrelight (Color 59624 8824 8995)
    widgetModifyBg clrBox StateActive (Color 59624 8824 8995)
    subBox <- builderGetObject builder castToEventBox "boxEq"
    widgetModifyBg subBox StateNormal (Color 0 65535 0)
    widgetModifyBg subBox StatePrelight (Color 0 65535 0)
    widgetModifyBg subBox StateActive (Color 0 65535 0)

    -- Global state
    hasAnswer <- newIORef False
    lastAnswer <- newIORef "0.0"

    window <- builderGetObject builder castToWindow "window1"
    _ <- on window objectDestroy mainQuit
    widgetModifyBg window StateNormal (Color 65535 65535 65535)

    _ <- on window keyPressEvent $ tryEvent $ do
        Just char <- eventKeyVal >>= (liftIO . keyvalToChar)
        guard $ isAscii char
        hasAnswer_ <- liftIO $ readIORef hasAnswer
        liftIO $ if isSymbol char || isPunctuation char
                 then append [char] mainLabel hasAnswer_
                 else overwrite [char] mainLabel hasAnswer_
        liftIO $ writeIORef hasAnswer False

    _ <- on window keyPressEvent $ tryEvent $ do
        "Return" <- fmap unpack eventKeyName
        liftIO $ submit mainLabel sideLabel hasAnswer lastAnswer

    _ <- on window keyPressEvent $ tryEvent $ do
        "BackSpace" <- fmap unpack eventKeyName
        liftIO $ delete mainLabel

    _ <- on window keyPressEvent $ tryEvent $ do
        "Delete" <- fmap unpack eventKeyName
        liftIO $ clear mainLabel sideLabel hasAnswer

    _ <- on window keyPressEvent $ tryEvent $ do
        "Escape" <- fmap unpack eventKeyName
        liftIO $ clear mainLabel sideLabel hasAnswer

    -- Bind all number/operator buttons
    forM_ textButtonBindings $ \(btnId,action) -> do
        button <- builderGetObject builder castToButton btnId
        on button buttonActivated $ do
            readIORef hasAnswer >>= action mainLabel
            writeIORef hasAnswer False

    -- Bind action buttons
    subButton <- builderGetObject builder castToButton "buttonEq"
    _ <- on subButton buttonActivated (submit mainLabel sideLabel hasAnswer lastAnswer)
    delButton <- builderGetObject builder castToButton "buttonDel"
    _ <- on delButton buttonActivated (delete mainLabel)
    clrButton <- builderGetObject builder castToButton "buttonClr"
    _ <- on clrButton buttonActivated (clear mainLabel sideLabel hasAnswer)
    ansButton <- builderGetObject builder castToButton "buttonAns"
    _ <- on ansButton buttonActivated (answer mainLabel hasAnswer lastAnswer)

    -- Display the window
    widgetShowAll window
    mainGUI


main :: IO ()
main = do
    _ <- initGUI
    -- Create the builder, and load the UI file
    builder <- builderNew
    builderAddFromString builder ($(embedStringFile "src-exe/calc.glade") :: String)

    mainLabel <- builderGetObject builder castToLabel "labelBig"
    sideLabel <- builderGetObject builder castToLabel "labelSmall"

    -- Fix UTF-8 sqrt symbol
    sqrtButton <- builderGetObject builder castToButton "buttonSqrt"
    mChild <- binGetChild sqrtButton
    case mChild of
        Just child -> labelSetText (castToLabel child) "√x"
        Nothing -> return ()

    -- Color EventBoxes (= workaround for button colors)
    delBox <- builderGetObject builder castToEventBox "boxDel"
    widgetModifyBg delBox StateNormal (Color 59624 8824 8995)
    widgetModifyBg delBox StatePrelight (Color 59624 8824 8995)
    widgetModifyBg delBox StateActive (Color 59624 8824 8995)
    clrBox <- builderGetObject builder castToEventBox "boxClr"
    widgetModifyBg clrBox StateNormal (Color 59624 8824 8995)
    widgetModifyBg clrBox StatePrelight (Color 59624 8824 8995)
    widgetModifyBg clrBox StateActive (Color 59624 8824 8995)
    subBox <- builderGetObject builder castToEventBox "boxEq"
    widgetModifyBg subBox StateNormal (Color 0 65535 0)
    widgetModifyBg subBox StatePrelight (Color 0 65535 0)
    widgetModifyBg subBox StateActive (Color 0 65535 0)

    -- Global state
    hasAnswer <- newIORef False
    lastAnswer <- newIORef "0.0"

    window <- builderGetObject builder castToWindow "window1"
    _ <- on window objectDestroy mainQuit
    widgetModifyBg window StateNormal (Color 65535 65535 65535)

    _ <- on window keyPressEvent $ tryEvent $ do
        Just char <- eventKeyVal >>= (liftIO . keyvalToChar)
        guard $ isAscii char
        hasAnswer_ <- liftIO $ readIORef hasAnswer
        liftIO $ if isSymbol char || isPunctuation char
                 then append [char] mainLabel hasAnswer_
                 else overwrite [char] mainLabel hasAnswer_
        liftIO $ writeIORef hasAnswer False

    _ <- on window keyPressEvent $ tryEvent $ do
        "Return" <- fmap unpack eventKeyName
        liftIO $ submit mainLabel sideLabel hasAnswer lastAnswer

    _ <- on window keyPressEvent $ tryEvent $ do
        "BackSpace" <- fmap unpack eventKeyName
        liftIO $ delete mainLabel

    _ <- on window keyPressEvent $ tryEvent $ do
        "Delete" <- fmap unpack eventKeyName
        liftIO $ clear mainLabel sideLabel hasAnswer

    _ <- on window keyPressEvent $ tryEvent $ do
        "Escape" <- fmap unpack eventKeyName
        liftIO $ clear mainLabel sideLabel hasAnswer

    -- Bind all number/operator buttons
    forM_ textButtonBindings $ \(btnId,action) -> do
        button <- builderGetObject builder castToButton btnId
        on button buttonActivated $ do
            readIORef hasAnswer >>= action mainLabel
            writeIORef hasAnswer False

    -- Bind action buttons
    subButton <- builderGetObject builder castToButton "buttonEq"
    _ <- on subButton buttonActivated (submit mainLabel sideLabel hasAnswer lastAnswer)
    delButton <- builderGetObject builder castToButton "buttonDel"
    _ <- on delButton buttonActivated (delete mainLabel)
    clrButton <- builderGetObject builder castToButton "buttonClr"
    _ <- on clrButton buttonActivated (clear mainLabel sideLabel hasAnswer)
    ansButton <- builderGetObject builder castToButton "buttonAns"
    _ <- on ansButton buttonActivated (answer mainLabel hasAnswer lastAnswer)

    -- Display the window
    widgetShowAll window
    mainGUI
main = do
    _ <- initGUI
    -- Create the builder, and load the UI file
    builder <- builderNew
    builderAddFromString builder ($(embedStringFile "src-exe/calc.glade") :: String)

    mainLabel <- builderGetObject builder castToLabel "labelBig"
    sideLabel <- builderGetObject builder castToLabel "labelSmall"

    -- Fix UTF-8 sqrt symbol
    sqrtButton <- builderGetObject builder castToButton "buttonSqrt"
    mChild <- binGetChild sqrtButton
    case mChild of
        Just child -> labelSetText (castToLabel child) "√x"
        Nothing -> return ()

    -- Color EventBoxes (= workaround for button colors)
    delBox <- builderGetObject builder castToEventBox "boxDel"
    widgetModifyBg delBox StateNormal (Color 59624 8824 8995)
    widgetModifyBg delBox StatePrelight (Color 59624 8824 8995)
    widgetModifyBg delBox StateActive (Color 59624 8824 8995)
    clrBox <- builderGetObject builder castToEventBox "boxClr"
    widgetModifyBg clrBox StateNormal (Color 59624 8824 8995)
    widgetModifyBg clrBox StatePrelight (Color 59624 8824 8995)
    widgetModifyBg clrBox StateActive (Color 59624 8824 8995)
    subBox <- builderGetObject builder castToEventBox "boxEq"
    widgetModifyBg subBox StateNormal (Color 0 65535 0)
    widgetModifyBg subBox StatePrelight (Color 0 65535 0)
    widgetModifyBg subBox StateActive (Color 0 65535 0)

    -- Global state
    hasAnswer <- newIORef False
    lastAnswer <- newIORef "0.0"

    window <- builderGetObject builder castToWindow "window1"
    _ <- on window objectDestroy mainQuit
    widgetModifyBg window StateNormal (Color 65535 65535 65535)

    _ <- on window keyPressEvent $ tryEvent $ do
        Just char <- eventKeyVal >>= (liftIO . keyvalToChar)
        guard $ isAscii char
        hasAnswer_ <- liftIO $ readIORef hasAnswer
        liftIO $ if isSymbol char || isPunctuation char
                 then append [char] mainLabel hasAnswer_
                 else overwrite [char] mainLabel hasAnswer_
        liftIO $ writeIORef hasAnswer False

    _ <- on window keyPressEvent $ tryEvent $ do
        "Return" <- fmap unpack eventKeyName
        liftIO $ submit mainLabel sideLabel hasAnswer lastAnswer

    _ <- on window keyPressEvent $ tryEvent $ do
        "BackSpace" <- fmap unpack eventKeyName
        liftIO $ delete mainLabel

    _ <- on window keyPressEvent $ tryEvent $ do
        "Delete" <- fmap unpack eventKeyName
        liftIO $ clear mainLabel sideLabel hasAnswer

    _ <- on window keyPressEvent $ tryEvent $ do
        "Escape" <- fmap unpack eventKeyName
        liftIO $ clear mainLabel sideLabel hasAnswer

    -- Bind all number/operator buttons
    forM_ textButtonBindings $ \(btnId,action) -> do
        button <- builderGetObject builder castToButton btnId
        on button buttonActivated $ do
            readIORef hasAnswer >>= action mainLabel
            writeIORef hasAnswer False

    -- Bind action buttons
    subButton <- builderGetObject builder castToButton "buttonEq"
    _ <- on subButton buttonActivated (submit mainLabel sideLabel hasAnswer lastAnswer)
    delButton <- builderGetObject builder castToButton "buttonDel"
    _ <- on delButton buttonActivated (delete mainLabel)
    clrButton <- builderGetObject builder castToButton "buttonClr"
    _ <- on clrButton buttonActivated (clear mainLabel sideLabel hasAnswer)
    ansButton <- builderGetObject builder castToButton "buttonAns"
    _ <- on ansButton buttonActivated (answer mainLabel hasAnswer lastAnswer)

    -- Display the window
    widgetShowAll window
    mainGUI