content: {-# LANGUAGE OverloadedStrings #-}
  
  module Hasmin.Types.StylesheetSpec where
  
  import Data.Text (Text, unpack)
  
  import Hasmin.Parser.Internal
  import Hasmin.TestUtils
  import Hasmin.Class
  import Hasmin.Types.Stylesheet
  import Hasmin
  
  combineAdjacentMediaQueriesTests :: Spec
  combineAdjacentMediaQueriesTests =
       describe "Combines adjacent @media rules" $
        mapM_ f combineAdjacentMediaQueriesTestsInfo
    where f (t1, t2) = it (unpack t1) $ minifyCSS t1 `parseSatisfies` (== t2)
  
  combineAdjacentMediaQueriesTestsInfo :: [(Text, Text)]
  combineAdjacentMediaQueriesTestsInfo =
    [("@media (min-width:24rem){.Fz\\(s2\\)\\@xs{font-size:1.2rem;}}@media (min-width:24rem){.Px\\(s04\\)\\@xs{padding-left:.25rem; padding-right:.25rem;}}",
      "@media (min-width:24rem){.Fz\\(s2\\)\\@xs{font-size:1.2rem}.Px\\(s04\\)\\@xs{padding-left:.25rem;padding-right:.25rem}}")
  
  
    {- TODO make Eq instance handle this equality.
     -
    ,("@media all and (min-width:24rem){.Fz\\(s2\\)\\@xs{font-size:1.2rem;}}@media (min-width:24rem){.Px\\(s04\\)\\@xs{padding-left:.25rem; padding-right:.25rem;}}",
      "@media (min-width:24rem){.Fz\\(s2\\)\\@xs{font-size:1.2rem}.Px\\(s04\\)\\@xs{padding-left:.25rem;padding-right:.25rem}}")
    -}
    ]
  
  atRuleTests :: Spec
  atRuleTests = do
      describe "at rules parsing and printing" $
        mapM_ (matchSpec atRule) atRuleTestsInfo
      describe "@supports minification" $
        mapM_ (matchSpec (minifyWithTestConfig <$> atRule)) atSupportsTestInfo
      describe "@import minification" $
        mapM_ (matchSpec (minifyWithTestConfig <$> atRule)) atImportTestInfo
      describe "@media minification" $
        mapM_ (matchSpec (minifyWithTestConfig <$> atRule)) atMediaTestInfo
  
  atMediaTestInfo :: [(Text, Text)]
  atMediaTestInfo =
    [("@media all {h1{color:red}}",
      "@media {h1{color:red}}")
    ,("@media all and (min-width: 500px){h1 {color: red}}",
      "@media (min-width:500px){h1{color:red}}")
    ,("@media not all{h1{color:red}}",
      "@media not all{h1{color:red}}")
    ,("@media all and (min-width:500px), not all and (min-device-pixel-ratio:0){h1{a:a}}",
      "@media (min-width:500px),not all and (min-device-pixel-ratio:0){h1{a:a}}")
    ,("@media (min-width:500px),all and (min-device-pixel-ratio:0){h1{a:a}}",
      "@media (min-width:500px),(min-device-pixel-ratio:0){h1{a:a}}")
    ,("@media only all{h1{a:a}}",
      "@media only all{h1{a:a}}")
    ]
  
  atImportTestInfo :: [(Text, Text)]
  atImportTestInfo =
    [("@import  url(\'landscape.css\');",
        "@import \"landscape.css\";")
    ,("@import url(landscape.css);",
        "@import \"landscape.css\";")
    ,("@import url(landscape.css) all;",
        "@import \"landscape.css\";")
    ,("@import url(landscape.css) screen, all and (min-width:500px);",
        "@import \"landscape.css\" screen,(min-width:500px);")
    ,("@import url(landscape.css) all and (min-width:500px);",
        "@import \"landscape.css\" (min-width:500px);")
    ]
  
  mergeRulesTest :: Spec
  mergeRulesTest =
      describe "Rules merging" $
        mapM_ (matchSpecWithDesc (f . minifyWithTestConfig <$> rules)) mergeRulesTestsInfo
    where f = mconcat . map toText
  
  mergeRulesTestsInfo :: [(String, Text, Text)]
  mergeRulesTestsInfo =
    [("Combine adjacent rules with the same declarations",
        "h1{margin:10px}h2{margin:10px}",
        "h1,h2{margin:10px}")
    ,("Merge rules with identical selectors, and combine margin-bottom into margin",
      ".a{margin:10px}.a{margin-bottom:5px}",
      ".a{margin:10px 10px 5px}")
    ,("Merge rules with identical selectors, and remove overwritten margin-bottom",
      ".a{margin-bottom:10px}.a{margin:5px}",
      ".a{margin:5px}")
    ,("Merge rules with identical declarations, when a same specificity rule is in-between but the declarations don't interfere",
      ".a{border-left-color:red}.b{border-right-color:blue}.c{border-left-color:red}",
      ".a,.c{border-left-color:red}.b{border-right-color:blue}")
    ,("Don't merge rules that share selectors, but not every selector",
      "table,video{margin:0}ol,ul{list-style:none}table{border-collapse:collapse}",
      "table,video{margin:0}ol,ul{list-style:none}table{border-collapse:collapse}")
    ,("Don't combine rules with the same selectors when there is another in-between with the same specificity and a declaration that clashes",
      ".a p{margin:10px 0}.b p{margin:10px auto}.a p{margin-bottom:5px}",
      ".a p{margin:10px 0}.b p{margin:10px auto}.a p{margin-bottom:5px}")
    ,("Merge example from csso/issues/217 properly",
      ".a{float:left}.b{background:red}.c{color:#fff}.d{text-decoration:none}.e{float:left}.d{float:left}",
      ".a,.e,.d{float:left}.b{background:red}.c{color:#fff}.d{text-decoration:none}")
    ,("When merging rules, ignores @keyframes rule inbetween",
      ".a{color:red}@keyframes foo{0%{frame:1}to{frame:2}}.b{color:red}",
      ".a,.b{color:red}@keyframes foo{0%{frame:1}to{frame:2}}")
    ,("When merging rules, ignores @font-face rule inbetween",
      ".a{color:red}@font-face{test:1}.b{color:red}",
      ".a,.b{color:red}@font-face{test:1}")
      {- TODO
    ,("Merge rules with identical selectors, and combine font-weight into font",
      ".a{font:700 65%/1.5 sans-serif}.a{font-weight:400}",
      ".a{font:400 65%/1.5 sans-serif}")
      -}
    {-TODO considering gzip, is implementing this worth it?
    ,("csso 1",
      "a{padding:0;margin:0}b{padding:0}",
      "a,b{padding:0}a{margin:0}")
    ,("csso 2",
      "a{padding:0}b{padding:0;margin:0}",
      "a,b{padding:0}b{margin:0}")
    ,("csso 3",
      "a{padding:0}b{padding:0;margin:0}c{margin:0}",
      "a,b{padding:0}b,c{margin:0}")
    ,("csso 4",
      "a{padding:0}elementWithAnAbsurdlyVeryLongName{padding:0;margin:0}c{margin:0}",
      "a{padding:v}elementWithAnAbsurdlyVeryLongName{padding:0;margin:0}c{margin:0}")
    ,("csso ",
      ".foo{margin:0;padding:2px}.bar{margin:1px;padding:2px}",
      ".bar,.foo{margin:0;padding:2px}.bar{margin:1px}")
    -}
    ]
  
  atSupportsTestInfo :: [(Text, Text)]
  atSupportsTestInfo =
    [("@supports not (not (a:a)){s{b:b}}",
        "@supports (a:a){s{b:b}}")
    ]
  
  -- TODO test for
  {-
  .gallery-loading .gallery-loading-container {
    background: #fff url("//corporate-website-test.s3.amazonaws.com/wp-content/themes/ggs-rcw/img/spinner_white_125px.gif") no-repeat center center;
  }
  -}
  atRuleTestsInfo :: [(Text, Text)]
  atRuleTestsInfo =
    [("@charset \"UTF-8\";",
        "@charset \"UTF-8\";")
    ,("@import/**/ 'custom.css' ;",
        "@import 'custom.css';")
    ,("@import  \"common.css\" screen , projection;",
        "@import \"common.css\" screen,projection;")
    ,("@import  url(\'landscape.css\')  screen  and  (orientation: landscape);",
        "@import url(\'landscape.css\') screen and (orientation:landscape);")
    ,("@namespace /**/ prefix url(XML-namespace-URL);",
        "@namespace prefix url(XML-namespace-URL);")
    ,("@namespace  prefix /**/  \"XML-namespace-URL\";",
        "@namespace prefix \"XML-namespace-URL\";")
    ,("@media screen {s{a:a}}",
        "@media screen{s{a:a}}")
    ,("@media screen and (min-width: 768px){s{a:a}}",
        "@media screen and (min-width:768px){s{a:a}}")
    ,("@keyframes p { from { background-position: 40px 0 } to { background-position: 0 0 } }",
        "@keyframes p{from{background-position:40px 0}to{background-position:0 0}}")
    ,("@font-face  /**/ {a:a;}",
        "@font-face{a:a}")
    -- Uncomment once custom properties are supported
    -- ,("@supports (--foo: green) { body { color: green; } }",
       -- "@supports (--foo:green){body{color:green}}")
    ,("@supports ( transform-style: preserve ) or ( -moz-transform-style: preserve ){s{a:a}}",
       "@supports (transform-style:preserve) or (-moz-transform-style:preserve){s{a:a}}")
    ,("@supports ( display : table-cell ) and ( not ( display : list-item ) ){s{a:a}}",
      "@supports (display:table-cell) and (not (display:list-item)){s{a:a}}")
    ,("@supports not ( (a:a)  and  (b:b) ) {s{a:a}}",
      "@supports not ((a:a) and (b:b)){s{a:a}}")
    ,("@supports ((yoyo: yaya) or (margin: 0) or (answer: 42)) { div { background-color:green; } }",
      "@supports ((yoyo:yaya) or (margin:0) or (answer:42)){div{background-color:green}}")
    ,("@supports (margin: 0) {@media  not  all { div { background-color:red; }}}",
      "@supports (margin:0){@media not all{div{background-color:red}}}")
    -- ,("@document url(http://www.w3.org/) , url-prefix(http://www.w3.org/Style/),\
    --             \ domain(mozilla.org), regexp(\"https:.*\")"
    -- ,("@document url(http://www.w3.org/),url-prefix(http://www.w3.org/Style/),\
      --           \domain(mozilla.org),regexp(\"https:.*\")"
    -- ,("@page { margin: 1in }",
    --   "@page{margin:1in}")
    -- ,("@page :left { font-size: 20pt; }",
      -- "@page:left{font-size:20pt}")
    -- ,("@page toc, index { size:8.5in 11in; }",
      -- "@page toc,index{size:8.5in 11in}")
    -- ,("@viewport { min-width: 640px; max-width: 800px; }",
      -- "@viewport{min-width:640px;max-width:800px}")
    -- ,("@counter-style circled-alpha { system: fixed; symbols: Ⓐ Ⓑ Ⓒ; suffix: " "; }",
      -- "@counter-style circled-alpha{system:fixed;symbols:Ⓐ Ⓑ Ⓒ;suffix:" "}")
    -- ,("@font-feature-values Jupiter Sans { @swash { delicate: 1; flowing: 2; } }",
      -- "@font-feature-values Jupiter Sans{@swash{delicate:1;flowing:2}}",
    ]
  
  collapseLonghandTests :: Spec
  collapseLonghandTests =
      describe "TRBL Longhand collapsing" $
        mapM_ (matchSpec f) collapseLonghandsTestsInfo
    where f = Declarations . collapse <$> declarations
  
  collapseLonghandsTestsInfo :: [(Text, Text)]
  collapseLonghandsTestsInfo =
    [("margin-top:1px;margin-right:2px;margin-bottom:3px;margin-left:4px",
      "margin:1px 2px 3px 4px")
    ,("margin-left:4px;margin-bottom:3px;margin-right:2px;margin-top:1px;",
      "margin:1px 2px 3px 4px")
    ,("margin-left:4px;margin-bottom:3px;padding-top:0;margin-right:2px;margin-top:1px;",
      "padding-top:0;margin:1px 2px 3px 4px")
    ,("margin-bottom:3px;padding-top:0;margin-right:2px;margin-top:1px;",
      "margin-bottom:3px;padding-top:0;margin-right:2px;margin-top:1px")
    ,("padding-left:4px;padding-bottom:3px;padding-right:2px;padding-top:1px;",
      "padding:1px 2px 3px 4px")
    ,("border-left-color:#004;border-bottom-color:#003;border-right-color:#002;border-top-color:#001;",
      "border-color:#001 #002 #003 #004")
    ]
  
  
  spec :: Spec
  spec = do atRuleTests
            combineAdjacentMediaQueriesTests
            collapseLonghandTests
            mergeRulesTest
  
  main :: IO ()
  main = hspec spec
  