content: {-# LANGUAGE OverloadedStrings #-}
  
  --
  -- Based on the Elm VegaLite AxisTests.elm in the 2.0 development version
  --
  module AxisTests (testSpecs) where
  
  import qualified Data.Text as T
  
  import Graphics.Vega.VegaLite
  
  import Prelude hiding (filter)
  
  testSpecs :: [(String, VegaLite)]
  testSpecs = [ ("axis1", axis1)
              , ("axis1c", axis1c)
              , ("axis2", axis2)
              , ("axis2c", axis2c)
              , ("axis3", axis3)
              , ("axis3c", axis3c)
              , ("axis4", axis4)
              , ("axis4c", axis4c)
              , ("axis5", axis5)
              , ("axis5c", axis5c)
              , ("axis6", axis6)
              , ("axis6c", axis6c)
              , ("axis7", axis7)
              , ("axis7c", axis7c)
              , ("axis8", axis8)
              , ("axis8c", axis8c)
              , ("axisOverlapNone", axisOverlapNone)
              , ("axisOverlapParity", axisOverlapParity)
              , ("axisOverlapGreedy", axisOverlapGreedy)
              , ("zorder", zorder)
              , ("responsiveWidth", responsiveWidth)
              , ("responsiveHeight", responsiveHeight)
              , ("axisstyleempty", axisStyleEmpty)
              , ("axisstyleemptyx", axisStyleEmptyX)
              , ("axisstylex", axisStyleX)
              , ("axisstylexastyle", axisStyleXAStyle)
              , ("axisstylexy", axisStyleXY)
              , ("singleline", singleLine)
              , ("multiline", multiLine)
              ]
  
  
  -- We do not provide these in hvega, so define them here to make copying
  -- the Elm tests over easier.
  --
  pOrdinal, pQuant, pTemporal :: PositionChannel
  pOrdinal = PmType Ordinal
  pQuant = PmType Quantitative
  pTemporal = PmType Temporal
  
  pName :: T.Text -> PositionChannel
  pName = PName
  
  
  simpleData :: Data
  simpleData =
    let xvals = map fromIntegral xs
        xs = [1::Int .. 100]
    in dataFromColumns []
         . dataColumn "x" (Numbers xvals)
         . dataColumn "catX" (Strings (map (T.pack . show) xs))
         . dataColumn "y" (Numbers xvals)
         $ []
  
  
  temporalData ::  Data
  temporalData =
    let dates = [ "2019-01-01 09:00:00"
                , "2019-01-02 09:00:00"
                , "2019-01-03 09:00:00"
                , "2019-01-04 09:00:00"
                , "2019-01-05 09:00:00"
                , "2019-01-06 09:00:00"
                , "2019-01-07 09:00:00"
                , "2019-01-08 09:00:00"
                , "2019-01-09 09:00:00"
                , "2019-01-10 09:00:00"
                , "2019-01-11 09:00:00"
                , "2019-01-12 09:00:00"
                ]
  
        xs = map fromIntegral [1::Int .. 12]
  
    in dataFromColumns []
       . dataColumn "date" (Strings dates)
       . dataColumn "y" (Numbers xs)
       $ []
  
  xQuant, yQuant, catX, xDate :: [PositionChannel]
  xQuant = [pName "x", pQuant]
  yQuant = [pName "y", pQuant]
  catX = [pName "catX", pOrdinal]
  xDate = [pName "date", pTemporal]
  
  
  axisBase :: Data -> [ConfigurationProperty] -> [PositionChannel] -> [PositionChannel] -> VegaLite
  axisBase plotData confOpts xOpts yOpts =
    let enc = encoding . position X xOpts . position Y yOpts
  
        conf = case confOpts of
                 [] -> []
                 _ -> [configure (foldr configuration [] confOpts)]
        vs = conf ++ [ plotData, enc [], mark Line [ MPoint (PMMarker []) ] ]
  
    in toVegaLite vs
  
  plotCfg :: [ConfigurationProperty]
  plotCfg = [ AxisQuantitative AxXY [ DomainColor "orange"
                                    , GridColor "seagreen"
                                    , LabelFont "Comic Sans MS"
                                    , LabelOffset 10
                                    , TickOffset 10
                                    ]
            , AxisTemporal AxXY [ DomainColor "brown"
                                , DomainDash [4, 2]
                                , Grid False
                                , LabelColor "purple"
                                ]
            , PointStyle [ MStroke "black"
                         , MStrokeOpacity 0.4
                         , MStrokeWidth 1
                         , MFill "yellow"
                         ]
            , LineStyle [ MStroke "gray"
                        , MStrokeWidth 2
                        ]
            ]
  
  
  axis1, axis1c, axis2, axis2c, axis3, axis3c, axis4, axis4c,
    axis5, axis5c, axis6, axis6c, axis7, axis7c, axis8, axis8c :: VegaLite
  axis1 = axisBase simpleData [] xQuant yQuant
  axis1c = axisBase simpleData plotCfg xQuant yQuant
  axis2 = axisBase simpleData [] catX yQuant
  axis2c = axisBase simpleData plotCfg catX yQuant
  axis3 = axisBase simpleData [] xDate yQuant
  axis3c = axisBase simpleData plotCfg xDate yQuant
  axis4 =
    let x = PAxis [AxValues (Numbers [1, 25, 39, 90])] : xQuant
    in axisBase simpleData [] x yQuant
  axis4c =
    let x = PAxis [AxValues (Numbers [1, 25, 39, 90])] : xQuant
    in axisBase simpleData plotCfg x yQuant
  axis5 =
    let x = PAxis [AxValues (Strings ["1", "25", "39", "dummy", "90"])] : catX
    in axisBase simpleData [] x yQuant
  axis5c =
    let x = PAxis [AxValues (Strings ["1", "25", "39", "dummy", "90"])] : catX
    in axisBase simpleData plotCfg x yQuant
  axis6 =
    let x = PAxis [AxValues (DateTimes axDates)] : xDate
  
        axDates = [ [DTYear 2019, DTMonth Jan, DTDate 4 ]
                  , [DTYear 2019, DTMonth Jan, DTDate 8 ]
                  , [DTYear 2019, DTMonth Jan, DTDate 20 ]
                  ]
  
    in axisBase temporalData [] x yQuant
  axis6c =
    let x = PAxis [AxValues (DateTimes axDates)] : xDate
  
        axDates = [ [DTYear 2019, DTMonth Jan, DTDate 4 ]
                  , [DTYear 2019, DTMonth Jan, DTDate 8 ]
                  , [DTYear 2019, DTMonth Jan, DTDate 20 ]
                  ]
  
    in axisBase temporalData plotCfg x yQuant
  axis7 =
    let x = PAxis [AxLabelExpr "datum.value / 100"] : xQuant
    in axisBase simpleData [] x yQuant
  axis7c =
    let x = PAxis [AxLabelExpr "datum.value / 100"] : xQuant
    in axisBase simpleData plotCfg x yQuant
  axis8 =
    let x = PAxis [AxLabelExpr "'number' + datum.label"] : catX
    in axisBase simpleData [] x yQuant
  axis8c =
    let x = PAxis [AxLabelExpr "'number' + datum.label"] : catX
    in axisBase simpleData plotCfg x yQuant
  
  
  overlap :: OverlapStrategy -> VegaLite
  overlap strat =
    let dvals = dataFromColumns []
                . dataColumn "x" (Numbers [ 0.1, 0.11, 0.2, 0.21, 0.5 ])
                . dataColumn "y" (Numbers [ 100, 101, 102, 103, 101 ])
  
        axisOpts = PAxis [ AxLabelOverlap strat
                         , AxLabelFontSize 20
                         ]
  
        enc = encoding
              . position X [ PName "x", PmType Quantitative, axisOpts ]
              . position Y [ PName "y", PmType Quantitative, axisOpts ]
  
    in toVegaLite [ dvals [], enc [], mark Circle [] ]
  
  
  axisOverlapNone :: VegaLite
  axisOverlapNone = overlap ONone
  
  axisOverlapParity :: VegaLite
  axisOverlapParity = overlap OParity
  
  axisOverlapGreedy :: VegaLite
  axisOverlapGreedy = overlap OGreedy
  
  
  -- From
  -- https://github.com/gicentre/elm-vegalite/issues/15#issuecomment-524527125
  --
  zorder :: VegaLite
  zorder =
    let dcols = dataFromColumns []
                . dataColumn "x" (Numbers [ 20, 10 ])
                . dataColumn "y" (Numbers [ 10, 20 ])
                . dataColumn "cat" (Strings [ "a", "b" ])
  
        axis lbl z = [ PName lbl, PmType Quantitative, PAxis [ AxZIndex z ] ]
        enc = encoding
              . position X (axis "x" 2)
              . position Y (axis "y" 1)
              . color [ MName "cat", MmType Nominal, MLegend [] ]
  
        cfg = configure
              . configuration (Axis [ GridWidth 8 ])
              . configuration (AxisX [ GridColor "red" ])
              . configuration (AxisY [ GridColor "blue" ])
  
    in toVegaLite [ cfg []
                  , dcols []
                  , enc []
                  , mark Circle [ MSize 5000, MOpacity 1 ]
                  ]
  
  
  responsive :: PropertySpec -> VegaLite
  responsive prop =
    let enc = encoding
              . position X [PName "x", PmType Quantitative]
              . position Y [PName "y", PmType Quantitative]
  
    in toVegaLite [ prop, simpleData, enc []
                  , mark Line [MPoint (PMMarker [])] ]
  
  responsiveWidth, responsiveHeight :: VegaLite
  responsiveWidth = responsive widthOfContainer
  responsiveHeight = responsive heightOfContainer
  
  
  carData :: Data
  carData = dataFromUrl "https://vega.github.io/vega-lite/data/cars.json" []
  
  
  carEnc :: [AxisProperty] -> [AxisProperty] -> PropertySpec
  carEnc xOpts yOpts =
    let toAxis n l o = position n ([ PName l, PmType Quantitative ]
                                   ++ if null o
                                      then []
                                      else [PAxis o])
  
    in encoding
       . toAxis X "Horsepower" xOpts
       . toAxis Y "Miles_per_Gallon" yOpts
       . color [ MName "Origin", MmType Nominal, MLegend [] ]
       $ []
  
  axisStyleEmpty :: VegaLite
  axisStyleEmpty =
    let cfg = configure
              . configuration (AxisNamedStyles [])
  
    in toVegaLite [ cfg []
                  , carData
                  , carEnc [] []
                  , mark Point []
                  ]
  
  axisStyleEmptyX :: VegaLite
  axisStyleEmptyX =
    let cfg = configure
              . configuration (AxisNamedStyles [("x-style", [])])
  
    in toVegaLite [ cfg []
                  , carData
                  , carEnc [AxStyle ["x-style"]] []
                  , mark Point []
                  ]
  
  
  axisStyleX :: VegaLite
  axisStyleX =
    let cfg = configure
              . configuration (AxisNamedStyles [("x-style", [ AxDomainColor "orange"
                                                            , AxGridColor "lightgreen"
                                                            , AxLabelExpr xexpr ])])
  
        xexpr = "if (datum.value <= 100, 'low:' + datum.label, 'high:' + datum.label)"
  
    in toVegaLite [ cfg []
                  , carData
                  , carEnc [AxStyle ["x-style"]] []
                  , mark Point []
                  ]
  
  
  -- check AStyle; should give same look as axisStyleX
  axisStyleXAStyle :: VegaLite
  axisStyleXAStyle =
    let cfg = configure
              . configuration (AxisNamedStyles [("x-style", [ AxDomainColor "orange"
                                                            , AxGridColor "lightgreen"
                                                            , AxLabelExpr xexpr ])])
              . configuration (AxisX [AStyle ["x-style"]])
  
        xexpr = "if (datum.value <= 100, 'low:' + datum.label, 'high:' + datum.label)"
  
    in toVegaLite [ cfg []
                  , carData
                  , carEnc [] []
                  , mark Point []
                  ]
  
  
  axisStyleXY :: VegaLite
  axisStyleXY =
    let cfg = configure
              . configuration (AxisNamedStyles [ ("x-style", [ AxDomainColor "orange"
                                                             , AxGridColor "lightgreen"
                                                             , AxLabelExpr xexpr ])
                                               , ("y-style", [ AxDomain False
                                                             , AxGrid False
                                                             , AxLabels False
                                                             , AxTicks False
                                                             , AxNoTitle ])
                                               ])
  
        xexpr = "if (datum.value <= 100, 'low:' + datum.label, 'high:' + datum.label)"
  
    in toVegaLite [ cfg []
                  , carData
                  , carEnc [AxStyle ["x-style"]] [AxStyle ["y-style"]]
                  , mark Point []
                  ]
  
  
  singleLine :: VegaLite
  singleLine =
    let xOpts = [ AxLabelExpr "datum.label + ' horses'" ]
        yOpts = [ AxLabelExpr "datum.label+' mpg'" ]
  
    in toVegaLite [ carData
                  , carEnc xOpts yOpts
                  , mark Point []
                  ]
  
  
  multiLine :: VegaLite
  multiLine =
    let xOpts = [ AxLabelExpr "datum.label + ' horses'"
                , AxLabelLineHeight 22
                , AxLabelFontSize 11
                ]
        yOpts = [ AxLabelExpr "datum.label+' mpg'"
                , AxLabelFontSize 22 ]
  
    in toVegaLite [ carData
                  , carEnc xOpts yOpts
                  , mark Point []
                  , configure
                    . configuration (LineBreakStyle " ")
                    . configuration (Axis [LabelLineHeight 20])
                    $ []
                  ]
  