{-# LANGUAGE OverloadedStrings #-}

--
-- Based on the Elm VegaLite GalleryBar.elm (from development of version
-- 1.13.0)
--
-- TODO: update to add new tests from Elm (v2.0)

module Gallery.Bar (testSpecs) where

import Graphics.Vega.VegaLite

import qualified Data.Text as T

import Prelude hiding (filter, lookup, repeat)

testSpecs :: [(String, VegaLite)]
testSpecs = [ ("bar1", bar1)
            , ("bar2", bar2)
            , ("bar3", bar3)
            , ("bar4", bar4)
            , ("bar5", bar5)
            , ("bar6", bar6)
            , ("bar6order", bar6order)
            , ("bar6sort", bar6sort)
            , ("bar7", bar7)
            , ("bar8", bar8)
            , ("bar9", bar9)
            , ("bar10", bar10)
            , ("bar11", bar11)
            , ("bar12", bar12)
            , ("bar13", bar13)
            , ("bar14", bar14)
            , ("agesorted", ageSorted)
            , ("explicitbins", explicitBins)
            , ("logscaled", logScaled)
            , ("signedpopulation", signedPopulation)
            , ("labeloverlay", labelOverlay)
            , ("wilkinsondotplot", wilkinsonDotPlot)
            , ("initialletter", initialLetter)
            , ("barnegative", barNegative)
            , ("baraxisspacesaving", barAxisSpaceSaving)
            , ("layer_bar_labels_grey", layerBarLabelsGrey)
            ]


pName :: T.Text -> PositionChannel
pName = PName

mName :: T.Text -> MarkChannel
mName = MName

pNominal, pOrdinal, pQuant :: PositionChannel
pNominal = PmType Nominal
pOrdinal = PmType Ordinal
pQuant = PmType Quantitative


noStroke :: [ConfigureSpec] -> PropertySpec
noStroke = configure
           . configuration (ViewStyle [ ViewNoStroke ])


seattleWeather :: Data
seattleWeather = dataFromUrl "https://vega.github.io/vega-lite/data/seattle-weather.csv" []

movieData :: Data
movieData = dataFromUrl "https://vega.github.io/vega-lite/data/movies.json" []


-- bar1 in GalleryBar.elm
bar1 :: VegaLite
bar1 =
    let
        des =
            description "A simple bar chart with embedded data."

        dvals =
            dataFromColumns []
                . dataColumn "a" (Strings [ "A", "B", "C", "D", "E", "F", "G", "H", "I" ])
                . dataColumn "b" (Numbers [ 28, 55, 43, 91, 81, 53, 19, 87, 52 ])

        enc =
            encoding
                . position X [ PName "a", PmType Ordinal ]
                . position Y [ PName "b", PmType Quantitative ]
    in
    toVegaLite [ des, dvals [], mark Bar [], enc [] ]


-- bar4 in GalleryBar.elm
bar2 :: VegaLite
bar2 =
    let
        des =
            description "Simple histogram of IMDB ratings."

        enc =
            encoding
                . position X [ PName "IMDB_Rating", PmType Quantitative, PBin [] ]
                . position Y [ PmType Quantitative, PAggregate Count ]
    in
    toVegaLite
        [ des
        , movieData
        , mark Bar [ MBinSpacing 0 ]
        , enc []
        ]


-- bar2 in GalleryBar.elm (except I've added a sorting specifier to Y)
bar3 :: VegaLite
bar3 =
    let
        des =
            description "A bar chart showing the US population distribution of age groups in 2000."

        trans =
            transform . filter (FExpr "datum.year == 2000")

        enc =
            encoding
                . position X [ PName "people"
                             , PmType Quantitative
                             , PAggregate Sum
                             , PAxis [ AxTitle "population" ] ]
                . position Y [ PName "age"
                             , PmType Ordinal
                             , PSort [ Descending ] ]
    in
    toVegaLite
        [ des
        , dataFromUrl "https://vega.github.io/vega-lite/data/population.json" []
        , mark Bar []
        , heightStep 17
        , trans []
        , enc []
        ]


-- bar7 in GalleryBar.elm
bar4 :: VegaLite
bar4 =
    let
        des =
            description "Grouped bar chart showing population structure by age and gender."

        trans =
            transform
                . filter (FExpr "datum.year == 2000")
                . calculateAs "datum.sex == 2 ? 'Female' : 'Male'" "gender"

        enc =
            encoding
                . position X [ PName "gender", PmType Nominal, PAxis [ AxNoTitle ] ]
                . position Y [ PName "people", PmType Quantitative, PAggregate Sum, PAxis [ AxTitle "population", AxGrid False ] ]
                . column [ FName "age", FmType Ordinal ]
                . color [ MName "gender", MmType Nominal, MScale [ SRange (RStrings [ "#EA98D2", "#659CCA" ]) ] ]

        config = noStroke
                . configuration (Axis [ DomainWidth 1 ])
    in
    toVegaLite
        [ des
        , dataFromUrl "https://vega.github.io/vega-lite/data/population.json" []
        , mark Bar []
        , widthStep 12
        , trans []
        , enc []
        , config []
        ]


-- bar8 in GalleryBar.elm
bar5 :: VegaLite
bar5 =
    let
        des =
            description "Seattle weather stacked bar chart"

        weatherColors =
            categoricalDomainMap
                [ ( "sun", "#e7ba52" )
                , ( "fog", "#c7c7c7" )
                , ( "drizzle", "#aec7ea" )
                , ( "rain", "#1f77b4" )
                , ( "snow", "#9467bd" )
                ]

        enc =
            encoding
                . position X [ PName "date"
                             , PmType Ordinal
                             , PTimeUnit (TU Month)
                             , PAxis [ AxTitle "Month of the year" ]
                             ]
                . position Y [ PmType Quantitative, PAggregate Count ]
                . color
                    [ MName "weather"
                    , MmType Nominal
                    , MScale weatherColors
                    , MLegend [ LTitle "Weather type" ]
                    ]
    in
    toVegaLite
        [ des
        , seattleWeather
        , mark Bar []
        , enc []
        ]


barley :: Data
barley = dataFromUrl "https://vega.github.io/vega-lite/data/barley.json" []


barleyEnc :: [EncodingSpec] -> PropertySpec
barleyEnc = encoding
            . position X [ PName "yield", PmType Quantitative, PAggregate Sum ]
            . position Y [ PName "variety", PmType Nominal ]
            . color [ MName "site", MmType Nominal ]


-- bar9 in GalleryBar.elm, also first version of
-- https://vega.github.io/vega-lite/docs/stack.html#sorting-stack-order
bar6 :: VegaLite
bar6 =
  let des = description "Barley crop yields as a horizontal stacked bar chart"

  in toVegaLite [ des
                , barley
                , mark Bar []
                , barleyEnc []
                ]


-- tweaks to bar6 from https://vega.github.io/vega-lite/docs/stack.html#sorting-stack-order
--
bar6order :: VegaLite
bar6order =
  let enc = barleyEnc
            . order [ OName "yield", OmType Quantitative, OAggregate Sum ]

  in toVegaLite [ barley
                , mark Bar []
                , enc []
                ]


-- tweaks to bar6 from https://vega.github.io/vega-lite/docs/stack.html#sorting-stack-order
--
bar6sort :: VegaLite
bar6sort =
  let enc = barleyEnc
            . order [ OName "siteOrder" ]

      trans = transform
              . calculateAs "if(datum.site === 'University Farm', 0, if(datum.site === 'Grand Rapids', 1, 2))" "siteOrder"

  in toVegaLite [ barley
                , trans []
                , mark Bar []
                , enc []
                ]


-- bar10 in GalleryBar.elm
bar7 :: VegaLite
bar7 =
    let
        des =
            description "Population structure as a normalised stacked bar chart."

        trans =
            transform
                . filter (FExpr "datum.year == 2000")
                . calculateAs "datum.sex == 2 ? 'Female' : 'Male'" "gender"

        enc =
            encoding
                . position X [ PName "age", PmType Ordinal ]
                . position Y [ PName "people"
                             , PmType Quantitative
                             , PAggregate Sum
                             , PAxis [ AxTitle "Population" ]
                             , PStack StNormalize
                             ]
                . color [ MName "gender"
                        , MmType Nominal
                        , MScale [ SRange (RStrings [ "#EA98D2", "#659CCA" ]) ]
                        ]
    in
    toVegaLite
        [ des
        , dataFromUrl "https://vega.github.io/vega-lite/data/population.json" []
        , trans []
        , mark Bar []
        , widthStep 17
        , enc []
        ]


-- bar11 in GalleryBar.elm
bar8 :: VegaLite
bar8 =
    let
        des =
            description "A simple bar chart with ranged data (aka Gantt Chart)."

        dvals =
            dataFromColumns []
                . dataColumn "task" (Strings [ "A", "B", "C" ])
                . dataColumn "start" (Numbers [ 1, 3, 8 ])
                . dataColumn "end" (Numbers [ 3, 8, 10 ])

        enc =
            encoding
                . position Y [ PName "task", PmType Ordinal ]
                . position X [ PName "start", PmType Quantitative ]
                . position X2 [ PName "end" ]
    in
    toVegaLite [ des, dvals [], mark Bar [], enc [] ]


-- bar12 in GalleryBar.elm
bar9 :: VegaLite
bar9 =
    let
        des =
            description "A bar chart that directly encodes color names in the data."

        dvals =
            dataFromColumns []
                . dataColumn "color" (Strings [ "red", "green", "blue" ])
                . dataColumn "b" (Numbers [ 28, 55, 43 ])

        enc =
            encoding
                . position X [ PName "color", PmType Nominal ]
                . position Y [ PName "b", PmType Quantitative ]
                . color [ MName "color", MmType Nominal, MScale [] ]
    in
    toVegaLite [ des, dvals [], mark Bar [], enc [] ]


-- bar13 in GalleryBar.elm
bar10 :: VegaLite
bar10 =
    let
        des =
            description "Layered bar chart showing the US population distribution of age groups and gender in 2000."

        trans =
            transform
                . filter (FExpr "datum.year == 2000")
                . calculateAs "datum.sex == 2 ? 'Female' : 'Male'" "gender"

        enc =
            encoding
                . position X [ PName "age", PmType Ordinal ]
                . position Y [ PName "people"
                             , PmType Quantitative
                             , PAggregate Sum
                             , PAxis [ AxTitle "Population" ]
                             , PStack NoStack
                             ]
                . color [ MName "gender"
                        , MmType Nominal
                        , MScale [ SRange (RStrings [ "#e377c2", "#1f77b4" ]) ]
                        ]
                . opacity [ MNumber 0.7 ]
    in
    toVegaLite
        [ des
        , dataFromUrl "https://vega.github.io/vega-lite/data/population.json" []
        , trans []
        , mark Bar []
        , widthStep 17
        , enc []
        ]


-- bar15 in GalleryBar.elm
bar11 :: VegaLite
bar11 =
    let
        des =
            description "A diverging stacked bar chart for sentiments towards a set of eight questions, displayed as percentages with neutral responses straddling the 0% mark."

        dvals =
            dataFromColumns []
                . dataColumn "question" (Strings [ "Q1", "Q1", "Q1", "Q1", "Q1", "Q2", "Q2", "Q2", "Q2", "Q2", "Q3", "Q3", "Q3", "Q3", "Q3", "Q4", "Q4", "Q4", "Q4", "Q4", "Q5", "Q5", "Q5", "Q5", "Q5", "Q6", "Q6", "Q6", "Q6", "Q6", "Q7", "Q7", "Q7", "Q7", "Q7", "Q8", "Q8", "Q8", "Q8", "Q8" ])
                . dataColumn "type" (Strings [ "Strongly disagree", "Disagree", "Neither agree nor disagree", "Agree", "Strongly agree", "Strongly disagree", "Disagree", "Neither agree nor disagree", "Agree", "Strongly agree", "Strongly disagree", "Disagree", "Neither agree nor disagree", "Agree", "Strongly agree", "Strongly disagree", "Disagree", "Neither agree nor disagree", "Agree", "Strongly agree", "Strongly disagree", "Disagree", "Neither agree nor disagree", "Agree", "Strongly agree", "Strongly disagree", "Disagree", "Neither agree nor disagree", "Agree", "Strongly agree", "Strongly disagree", "Disagree", "Neither agree nor disagree", "Agree", "Strongly agree", "Strongly disagree", "Disagree", "Neither agree nor disagree", "Agree", "Strongly agree" ])
                . dataColumn "value" (Numbers [ 24, 294, 594, 1927, 376, 2, 2, 0, 7, 11, 2, 0, 2, 4, 2, 0, 2, 1, 7, 6, 0, 1, 3, 16, 4, 1, 1, 2, 9, 3, 0, 0, 1, 4, 0, 0, 0, 0, 0, 2 ])
                . dataColumn "percentage" (Numbers [ 0.7, 9.1, 18.5, 59.9, 11.7, 18.2, 18.2, 0, 63.6, 0, 20, 0, 20, 40, 20, 0, 12.5, 6.3, 43.8, 37.5, 0, 4.2, 12.5, 66.7, 16.7, 6.3, 6.3, 12.5, 56.3, 18.8, 0, 0, 20, 80, 0, 0, 0, 0, 0, 100 ])
                . dataColumn "percentage_start" (Numbers [ -19.1, -18.4, -9.2, 9.2, 69.2, -36.4, -18.2, 0, 0, 63.6, -30, -10, -10, 10, 50, -15.6, -15.6, -3.1, 3.1, 46.9, -10.4, -10.4, -6.3, 6.3, 72.9, -18.8, -12.5, -6.3, 6.3, 62.5, -10, -10, -10, 10, 90, 0, 0, 0, 0, 0 ])
                . dataColumn "percentage_end" (Numbers [ -18.4, -9.2, 9.2, 69.2, 80.9, -18.2, 0, 0, 63.6, 63.6, -10, -10, 10, 50, 70, -15.6, -3.1, 3.1, 46.9, 84.4, -10.4, -6.3, 6.3, 72.9, 89.6, -12.5, -6.3, 6.3, 62.5, 81.3, -10, -10, 10, 90, 90, 0, 0, 0, 0, 100 ])

        enc =
            encoding
                . position X [ PName "percentage_start", PmType Quantitative, PAxis [ AxTitle "Percentage" ] ]
                . position X2 [ PName "percentage_end" ]
                . position Y [ PName "question", PmType Nominal, PAxis [ AxTitle "Question", AxOffset 5, AxTicks False, AxMinExtent 60, AxDomain False ] ]
                . color
                    [ MName "type"
                    , MmType Nominal
                    , MLegend [ LTitle "Response" ]
                    , MScale (SType ScOrdinal
                             : categoricalDomainMap
                                [ ( "Strongly disagree", "#c30d24" )
                                , ( "Disagree", "#f3a583" )
                                , ( "Neither agree nor disagree", "#cccccc" )
                                , ( "Agree", "#94c6da" )
                                , ( "Strongly agree", "#1770ab" )
                                ]
                             )
                    ]
    in
    toVegaLite [ des, dvals [], mark Bar [], enc [] ]


-- bar16 in GalleryBar.elm
bar12 :: VegaLite
bar12 =
    let
        des =
            description "A simple bar chart with embedded data labels."

        dvals =
            dataFromColumns []
                . dataColumn "a" (Strings [ "A", "B", "C" ])
                . dataColumn "b" (Numbers [ 28, 55, 43 ])

        enc =
            encoding
                . position X [ PName "b", PmType Quantitative ]
                . position Y [ PName "a", PmType Ordinal ]

        specBar =
            asSpec [mark Bar [] ]

        specText =
            asSpec [ mark Text [ MStyle [ "label" ] ]
                   , encoding (text [ TName "b", TmType Quantitative ] [])
                   ]

        config =
            configure . configuration (MarkNamedStyles
                                       [( "label"
                                        , [ MAlign AlignLeft, MBaseline AlignMiddle, MdX 3 ])])
    in
    toVegaLite [ des, dvals [], enc [], layer [ specBar, specText ], config [] ]


toRows :: T.Text -> [( T.Text, Int )] -> [DataRow] -> [DataRow]
toRows country animalFreqs oldRows =
    let
        toRow animal n =
            dataRow
                [ ( "country", Str country )
                , ( "animal", Str animal )
                , ( "col", Number (fromIntegral n) )
                ]

        fToCol ( animal, f ) =
            foldr (toRow animal) [] [1 .. f]

        newRows = concatMap fToCol animalFreqs
        
    in oldRows ++ newRows


-- bar19 in GalleryBar.elm
bar13 :: VegaLite
bar13 =
    let
        cow =
            "M4 -2c0 0 0.9 -0.7 1.1 -0.8c0.1 -0.1 -0.1 0.5 -0.3 0.7c-0.2 0.2 1.1 1.1 1.1 1.2c0 0.2 -0.2 0.8 -0.4 0.7c-0.1 0 -0.8 -0.3 -1.3 -0.2c-0.5 0.1 -1.3 1.6 -1.5 2c-0.3 0.4 -0.6 0.4 -0.6 0.4c0 0.1 0.3 1.7 0.4 1.8c0.1 0.1 -0.4 0.1 -0.5 0c0 0 -0.6 -1.9 -0.6 -1.9c-0.1 0 -0.3 -0.1 -0.3 -0.1c0 0.1 -0.5 1.4 -0.4 1.6c0.1 0.2 0.1 0.3 0.1 0.3c0 0 -0.4 0 -0.4 0c0 0 -0.2 -0.1 -0.1 -0.3c0 -0.2 0.3 -1.7 0.3 -1.7c0 0 -2.8 -0.9 -2.9 -0.8c-0.2 0.1 -0.4 0.6 -0.4 1c0 0.4 0.5 1.9 0.5 1.9l-0.5 0l-0.6 -2l0 -0.6c0 0 -1 0.8 -1 1c0 0.2 -0.2 1.3 -0.2 1.3c0 0 0.3 0.3 0.2 0.3c0 0 -0.5 0 -0.5 0c0 0 -0.2 -0.2 -0.1 -0.4c0 -0.1 0.2 -1.6 0.2 -1.6c0 0 0.5 -0.4 0.5 -0.5c0 -0.1 0 -2.7 -0.2 -2.7c-0.1 0 -0.4 2 -0.4 2c0 0 0 0.2 -0.2 0.5c-0.1 0.4 -0.2 1.1 -0.2 1.1c0 0 -0.2 -0.1 -0.2 -0.2c0 -0.1 -0.1 -0.7 0 -0.7c0.1 -0.1 0.3 -0.8 0.4 -1.4c0 -0.6 0.2 -1.3 0.4 -1.5c0.1 -0.2 0.6 -0.4 0.6 -0.4z"

        pig =
            "M1.2 -2c0 0 0.7 0 1.2 0.5c0.5 0.5 0.4 0.6 0.5 0.6c0.1 0 0.7 0 0.8 0.1c0.1 0 0.2 0.2 0.2 0.2c0 0 -0.6 0.2 -0.6 0.3c0 0.1 0.4 0.9 0.6 0.9c0.1 0 0.6 0 0.6 0.1c0 0.1 0 0.7 -0.1 0.7c-0.1 0 -1.2 0.4 -1.5 0.5c-0.3 0.1 -1.1 0.5 -1.1 0.7c-0.1 0.2 0.4 1.2 0.4 1.2l-0.4 0c0 0 -0.4 -0.8 -0.4 -0.9c0 -0.1 -0.1 -0.3 -0.1 -0.3l-0.2 0l-0.5 1.3l-0.4 0c0 0 -0.1 -0.4 0 -0.6c0.1 -0.1 0.3 -0.6 0.3 -0.7c0 0 -0.8 0 -1.5 -0.1c-0.7 -0.1 -1.2 -0.3 -1.2 -0.2c0 0.1 -0.4 0.6 -0.5 0.6c0 0 0.3 0.9 0.3 0.9l-0.4 0c0 0 -0.4 -0.5 -0.4 -0.6c0 -0.1 -0.2 -0.6 -0.2 -0.5c0 0 -0.4 0.4 -0.6 0.4c-0.2 0.1 -0.4 0.1 -0.4 0.1c0 0 -0.1 0.6 -0.1 0.6l-0.5 0l0 -1c0 0 0.5 -0.4 0.5 -0.5c0 -0.1 -0.7 -1.2 -0.6 -1.4c0.1 -0.1 0.1 -1.1 0.1 -1.1c0 0 -0.2 0.1 -0.2 0.1c0 0 0 0.9 0 1c0 0.1 -0.2 0.3 -0.3 0.3c-0.1 0 0 -0.5 0 -0.9c0 -0.4 0 -0.4 0.2 -0.6c0.2 -0.2 0.6 -0.3 0.8 -0.8c0.3 -0.5 1 -0.6 1 -0.6z"

        sheep =
            "M-4.1 -0.5c0.2 0 0.2 0.2 0.5 0.2c0.3 0 0.3 -0.2 0.5 -0.2c0.2 0 0.2 0.2 0.4 0.2c0.2 0 0.2 -0.2 0.5 -0.2c0.2 0 0.2 0.2 0.4 0.2c0.2 0 0.2 -0.2 0.4 -0.2c0.1 0 0.2 0.2 0.4 0.1c0.2 0 0.2 -0.2 0.4 -0.3c0.1 0 0.1 -0.1 0.4 0c0.3 0 0.3 -0.4 0.6 -0.4c0.3 0 0.6 -0.3 0.7 -0.2c0.1 0.1 1.4 1 1.3 1.4c-0.1 0.4 -0.3 0.3 -0.4 0.3c-0.1 0 -0.5 -0.4 -0.7 -0.2c-0.3 0.2 -0.1 0.4 -0.2 0.6c-0.1 0.1 -0.2 0.2 -0.3 0.4c0 0.2 0.1 0.3 0 0.5c-0.1 0.2 -0.3 0.2 -0.3 0.5c0 0.3 -0.2 0.3 -0.3 0.6c-0.1 0.2 0 0.3 -0.1 0.5c-0.1 0.2 -0.1 0.2 -0.2 0.3c-0.1 0.1 0.3 1.1 0.3 1.1l-0.3 0c0 0 -0.3 -0.9 -0.3 -1c0 -0.1 -0.1 -0.2 -0.3 -0.2c-0.2 0 -0.3 0.1 -0.4 0.4c0 0.3 -0.2 0.8 -0.2 0.8l-0.3 0l0.3 -1c0 0 0.1 -0.6 -0.2 -0.5c-0.3 0.1 -0.2 -0.1 -0.4 -0.1c-0.2 -0.1 -0.3 0.1 -0.4 0c-0.2 -0.1 -0.3 0.1 -0.5 0c-0.2 -0.1 -0.1 0 -0.3 0.3c-0.2 0.3 -0.4 0.3 -0.4 0.3l0.2 1.1l-0.3 0l-0.2 -1.1c0 0 -0.4 -0.6 -0.5 -0.4c-0.1 0.3 -0.1 0.4 -0.3 0.4c-0.1 -0.1 -0.2 1.1 -0.2 1.1l-0.3 0l0.2 -1.1c0 0 -0.3 -0.1 -0.3 -0.5c0 -0.3 0.1 -0.5 0.1 -0.7c0.1 -0.2 -0.1 -1 -0.2 -1.1c-0.1 -0.2 -0.2 -0.8 -0.2 -0.8c0 0 -0.1 -0.5 0.4 -0.8z"

        des =
            description "Isotype bar chart inspired by this Only An Ocean Between, 1943. Population Live Stock, p.13."

        dvals =
            dataFromRows []
                . toRows "Great Britain" [ ( "cattle", 3 ), ( "pigs", 2 ), ( "sheep", 10 ) ]
                . toRows "United States" [ ( "cattle", 9 ), ( "pigs", 6 ), ( "sheep", 7 ) ]

        enc =
            encoding
                . position X [ PName "col", PmType Ordinal, PAxis [] ]
                . position Y [ PName "animal", PmType Ordinal, PAxis [] ]
                . row [ FName "country", FmType Nominal, FHeader [ HNoTitle ] ]
                . shape
                    [ MName "animal"
                    , MmType Nominal
                    , MScale
                        (categoricalDomainMap
                            [ ( "person", "circle" )
                            , ( "cattle", cow )
                            , ( "pigs", pig )
                            , ( "sheep", sheep )
                            ]
                        )
                    , MLegend []
                    ]
                . color
                    [ MName "animal"
                    , MmType Nominal
                    , MLegend []
                    , MScale 
                        (categoricalDomainMap
                            [ ( "person", "rgb(162,160,152)" )
                            , ( "cattle", "rgb(194,81,64)" )
                            , ( "pigs", "rgb(93,93,93)" )
                            , ( "sheep", "rgb(91,131,149)" )
                            ]
                        )
                    ]
                . opacity [ MNumber 1 ]
                . size [ MNumber 200 ]
    in
    toVegaLite [ des, noStroke [], width 800, height 200, dvals [], mark Point [ MFilled True ], enc [] ]


-- bar20 in GalleryBar.elm
bar14 :: VegaLite
bar14 =
    let
        des =
            description "Isotype bar chart using emojis for symbols"

        dvals =
            dataFromRows []
                . toRows "Great Britain" [ ( "cattle", 3 ), ( "pigs", 2 ), ( "sheep", 10 ) ]
                . toRows "United States" [ ( "cattle", 9 ), ( "pigs", 6 ), ( "sheep", 7 ) ]

        trans =
            transform
                . calculateAs "{'cattle': '🐄', 'pigs': '🐖', 'sheep': '🐏'}[datum.animal]" "emoji"
                . window [ ( [ WOp Rank ], "rank" ) ] [ WGroupBy [ "country", "animal" ] ]

        enc =
            encoding
                . position X [ PName "rank", PmType Ordinal, PAxis [] ]
                . position Y [ PName "animal", PmType Nominal, PAxis [], PSort [] ]
                . row [ FName "country", FmType Nominal, FHeader [ HNoTitle ] ]
                . text [ TName "emoji", TmType Nominal ]
                . size [ MNumber 65 ]
    in
    toVegaLite [ des, noStroke [], width 800, height 200, dvals [], trans [], mark Text [ MBaseline AlignMiddle ], enc [] ]


-- bar3 in GalleryBar.elm, see bar3 above
ageSorted :: VegaLite
ageSorted =
  let des = description "A bar chart showing the US population distribution of age groups in 2000, sorted by population"

      dvals = dataFromUrl "https://vega.github.io/vega-lite/data/population.json" []

      trans = transform . filter (FExpr "datum.year == 2000")

      enc = encoding
            . position X [ PName "people"
                         , PmType Quantitative
                         , PAggregate Sum
                         , PAxis [ AxTitle "population" ]
                         ]
            . position Y [ PName "age"
                         , PmType Ordinal
                         , PSort [ ByChannel ChX
                                 , Descending ]
                         ]

  in toVegaLite [ des
                , heightStep 17
                , dvals
                , trans []
                , enc []
                , mark Bar []
                ]


-- bar5 in GalleryBar.elm
explicitBins :: VegaLite
explicitBins =
  let dvals = dataFromColumns []
              . dataColumn "binStart" (Numbers [ 8, 10, 12, 14, 16, 18, 20, 22 ])
              . dataColumn "binEnd" (Numbers [ 10, 12, 14, 16, 18, 20, 22, 24 ])
              . dataColumn "count" (Numbers [ 7, 29, 71, 127, 94, 54, 17, 5 ])

      enc = encoding
            . position X [ pName "binStart"
                         , pQuant
                         , PBin [ Step 2 ] ]
            . position X2 [ pName "binEnd" ]
            . position Y [ pName "count"
                         , pQuant ]

  in toVegaLite [ dvals [], enc [], mark Bar [] ]


-- bar6 in GalleryBar.elm
logScaled :: VegaLite
logScaled =
  let des = description "Log-scaled Histogram (may improve after https://github.com/vega/vega-lite/issues/4792)"

      dvals = dataFromColumns []
              . dataColumn "x" (Numbers [ 0.01, 0.1, 1, 1, 1, 1, 10, 10, 100, 500, 800 ])

      trans = transform
              . calculateAs "log(datum.x)/log(10)" "logX"
              . binAs [] "logX" "binLogX"
              . calculateAs "pow(10,datum.binLogX)" "x1"
              . calculateAs "pow(10,datum.binLogX_end)" "x2"

      enc = encoding
            . position X [ pName "x1"
                         , pQuant
                         , PScale [ SType ScLog, SBase 10 ]
                         , PAxis [ AxTickCount 5 ]
                         ]
            . position X2 [ pName "x2" ]
            . position Y [ PAggregate Count, pQuant ]

  in toVegaLite [ des, dvals [], trans [], enc [], mark Bar [] ]


-- bar14 in GalleryBar.elm
signedPopulation :: VegaLite
signedPopulation =
  let dvals = dataFromUrl "https://vega.github.io/vega-lite/data/population.json" []

      trans = transform
              . filter (FExpr "datum.year == 2000")
              . calculateAs "datum.sex == 2 ? 'Female' : 'Male'" "gender"
              . calculateAs "datum.sex == 2 ? datum.people : -datum.people" "signedPeople"

      enc = encoding
            . position Y [ pName "age"
                         , pOrdinal
                         , PAxis []
                         , PSort [ Descending ]
                         ]
            . position X [ pName "signedPeople"
                         , PAggregate Sum
                         , pQuant
                         , PAxis [ AxTitle "Population", AxFormat "s" ]
                         ]
            . color [ mName "gender"
                    , MmType Nominal
                    , MScale [ SRange (RStrings [ "#675193", "#ca8861" ]) ]
                    , MLegend [ LOrient LOTop, LTitle "" ]
                    ]

      cfg = noStroke
            . configuration (Axis [ Grid False ])

  in toVegaLite [ width 300
                , height 200
                , cfg []
                , dvals
                , trans []
                , enc []
                , mark Bar [] ]


-- bar17 in GalleryBar.elm
labelOverlay :: VegaLite
labelOverlay =
  let des = description "Bar chart with label overlay"

      trans = transform
              . calculateAs "isValid(datum.Major_Genre)? datum.Major_Genre : 'unclassified'" "genre"

      enc = encoding
            . position Y
                    [ pName "genre"
                    , pNominal
                    , PSort
                        [ CustomSort
                            (Strings
                                [ "Action"
                                , "Adventure"
                                , "Comedy"
                                , "Black Comedy"
                                , "Romantic Comedy"
                                , "Concert/Performance"
                                , "Documentary"
                                , "Drama"
                                , "Horror"
                                , "Musical"
                                , "Thriller/Suspense"
                                , "Western"
                                , "unclassified"
                                ]
                            )
                        ]
                    , PAxis []
                    ]

      encBar = encoding
               . position X
                    [ pName "IMDB_Rating"
                    , PAggregate Mean
                    , pQuant
                    , PScale [ SDomain (DNumbers [ 0, 10 ]) ]
                    , PTitle "Mean IMDB Ratings"
                    ]

      specBar =asSpec [ encBar [], mark Bar [ MColor "#ddd" ] ]

      encText = encoding
                . text [ TName "genre", TmType Nominal ]
                . detail [ DAggregate Count, DmType Quantitative ]

      specText = asSpec [ encText [], mark Text [ MAlign AlignCenter, MdX 5 ] ]

  in toVegaLite
        [ des
        , width 200
        , heightStep 16
        , movieData
        , trans []
        , enc []
        , layer [ specBar, specText ]
        ]


-- bar18 in GalleryBar.elm
wilkinsonDotPlot :: VegaLite
wilkinsonDotPlot =
  let desc = description "A Wilkinson dot plot"

      dvals = dataFromColumns []
              . dataColumn "data" (Numbers [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4 ])

      trans = transform
              . window [ ( [ WOp Rank, WField "rank" ], "id" ) ] [ WGroupBy [ "data" ] ]

      enc = encoding
            . position X [ pName "data", pOrdinal ]
            . position Y
                    [ pName "id"
                    , pOrdinal
                    , PAxis []
                    , PSort [ Descending ]
                    ]

  in toVegaLite
        [ desc
        , noStroke []
        , height 100
        , dvals []
        , trans []
        , enc []
        , mark Circle [ MOpacity 1 ]
        ]


-- From https://vega.github.io/vega-lite/examples/bar_month_temporal_initial.html
-- but teaked to add a few bar properties.
--
initialLetter :: VegaLite
initialLetter =
  let desc = "Using `labelExpr` to show only initial letters of month names."

  in toVegaLite [ description desc
                , width 400
                , height 300
                , seattleWeather
                , mark Bar [ MBlend BMDifference
                           , MColorGradient GrLinear
                             [ (0, "orange"), (1, "cyan") ]
                             []
                           , MCornerRadius 10
                           , MStroke "yellow"
                           , MStrokeWidth 4
                           , MTooltip TTData
                           ]
                , encoding
                  . position X [ PName "date"
                               , PmType Temporal
                               , PTimeUnit (TU Month)
                               , PAxis [ AxLabelAlign AlignLeft
                                       , AxLabelExpr "datum.label[0]"
                                       ]
                               ]
                  . position Y [ PName "precipitation"
                               , PmType Quantitative
                               , PAggregate Mean
                               ]
                  $ []
                ]


-- From https://vega.github.io/vega-lite/examples/bar_negative.html
--
barNegative :: VegaLite
barNegative =
  let desc = "A bar chart with negative values. We can hide the axis domain line, and instead use a conditional grid color to draw a zero baseline."

      barData = dataFromColumns []
                . dataColumn "a" (Strings ["A", "B", "C", "D", "E", "F", "G", "H", "I"])
                . dataColumn "b" (Numbers [-28, 55, -33, 91, 81, 53, -19, 87, 52])
                $ []

  in toVegaLite [ description desc
                , barData
                , mark Bar []
                , encoding
                  . position X [ PName "a"
                               , PmType Ordinal
                               , PAxis [ AxDomain False
                                       , AxTicks False
                                       , AxLabelAngle 0
                                       , AxLabelPadding 4 ]
                               ]
                  . position Y [ PName "b"
                               , PmType Quantitative
                               , PAxis [ AxDataCondition
                                         (Expr "datum.value === 0")
                                         (CAxGridColor "black" "#ddd")
                                       ]
                               ]
                  $ []
                ]


-- https://vega.github.io/vega-lite/examples/bar_axis_space_saving.html
barAxisSpaceSaving :: VegaLite
barAxisSpaceSaving =
  let desc = "Bar Chart with a spacing-saving y-axis"

      enc = encoding
            . position X [PAggregate Count, PmType Quantitative, PAxis [AxGrid False]]
            . position Y [ PName "Origin"
                         , PmType Nominal
                         , PScale [SPadding 0]
                         , PBand 0.5
                         , PAxis yAx
                         ]

      yAx = [ AxBandPosition 0
            , AxGrid True
            , AxDomain False
            , AxTicks False
            , AxLabelAlign AlignLeft
            , AxLabelBaseline AlignMiddle
            , AxLabelPadding (-5)
            , AxLabelOffset (-15)
            , AxTitleX 5
            , AxTitleY (-5)
            , AxTitleAngle 0
            , AxTitleAlign AlignLeft
            ]

  in toVegaLite [ description desc
                , dataFromUrl "https://vega.github.io/vega-lite/data/cars.json" []
                , heightStep 50
                , mark Bar [MYOffset 5, MCornerRadiusEnd 2]
                , enc []
                ]


-- https://vega.github.io/vega-lite/examples/layer_bar_labels_grey.html
layerBarLabelsGrey :: VegaLite
layerBarLabelsGrey =
  let baseEnc = encoding
                . position Y [PName "Major_Genre", PmType Nominal, PAxis []]

      plot1 = [ mark Bar [MColor "#ddd"]
              , encoding
                . position X [ PAggregate Mean
                             , PName "IMDB_Rating"
                             , PmType Quantitative
                             , PScale [SDomain (DNumbers [0, 10])]
                             , PTitle "Mean IMDB Ratings"
                             ]
                $ []
              ]

      plot2 = [ mark Text [MAlign AlignLeft, MX 5]
              , encoding
                . text [TName "Major_Genre", TmType Nominal]
                . detail [DAggregate Count, DmType Quantitative]
                $ []
              ]

  in toVegaLite [ width 200
                , heightStep 16
                , movieData
                , baseEnc []
                , layer [asSpec plot1, asSpec plot2]
                ]