content: {-# LANGUAGE LambdaCase #-}
  {-# LANGUAGE NoImplicitPrelude #-}
  
  module Language.Haskell.Brittany.Internal.Transformations.Columns where
  
  import qualified Data.Generics.Uniplate.Direct as Uniplate
  import qualified GHC.OldList as List
  import Language.Haskell.Brittany.Internal.Prelude
  import Language.Haskell.Brittany.Internal.Types
  
  
  
  transformSimplifyColumns :: BriDoc -> BriDoc
  transformSimplifyColumns = Uniplate.rewrite $ \case
    -- BDWrapAnnKey annKey bd ->
    --   BDWrapAnnKey annKey $ transformSimplify bd
    BDEmpty -> Nothing
    BDLit{} -> Nothing
    BDSeq list
      | any
        (\case
          BDSeq{} -> True
          BDEmpty{} -> True
          _ -> False
        )
        list
      -> Just $ BDSeq $ list >>= \case
        BDEmpty -> []
        BDSeq l -> l
        x -> [x]
    BDSeq (BDCols sig1 cols1@(_ : _) : rest)
      | all
        (\case
          BDSeparator -> True
          _ -> False
        )
        rest
      -> Just $ BDCols sig1 (List.init cols1 ++ [BDSeq (List.last cols1 : rest)])
    BDLines lines
      | any
        (\case
          BDLines{} -> True
          BDEmpty{} -> True
          _ -> False
        )
        lines
      -> Just $ BDLines $ filter isNotEmpty $ lines >>= \case
        BDLines l -> l
        x -> [x]
    -- prior floating in
    BDAnnotationPrior annKey1 (BDSeq (l : lr)) ->
      Just $ BDSeq (BDAnnotationPrior annKey1 l : lr)
    BDAnnotationPrior annKey1 (BDLines (l : lr)) ->
      Just $ BDLines (BDAnnotationPrior annKey1 l : lr)
    BDAnnotationPrior annKey1 (BDCols sig (l : lr)) ->
      Just $ BDCols sig (BDAnnotationPrior annKey1 l : lr)
    -- post floating in
    BDAnnotationRest annKey1 (BDSeq list) ->
      Just $ BDSeq $ List.init list ++ [BDAnnotationRest annKey1 $ List.last list]
    BDAnnotationRest annKey1 (BDLines list) ->
      Just
        $ BDLines
        $ List.init list
        ++ [BDAnnotationRest annKey1 $ List.last list]
    BDAnnotationRest annKey1 (BDCols sig cols) ->
      Just
        $ BDCols sig
        $ List.init cols
        ++ [BDAnnotationRest annKey1 $ List.last cols]
    BDAnnotationKW annKey1 kw (BDSeq list) ->
      Just
        $ BDSeq
        $ List.init list
        ++ [BDAnnotationKW annKey1 kw $ List.last list]
    BDAnnotationKW annKey1 kw (BDLines list) ->
      Just
        $ BDLines
        $ List.init list
        ++ [BDAnnotationKW annKey1 kw $ List.last list]
    BDAnnotationKW annKey1 kw (BDCols sig cols) ->
      Just
        $ BDCols sig
        $ List.init cols
        ++ [BDAnnotationKW annKey1 kw $ List.last cols]
    -- ensureIndent float-in
    -- not sure if the following rule is necessary; tests currently are
    -- unaffected.
    -- BDEnsureIndent indent (BDLines lines) ->
    --   Just $ BDLines $ BDEnsureIndent indent <$> lines
    -- matching col special transformation
    BDCols sig1 cols1@(_ : _)
      | BDLines lines@(_ : _ : _) <- List.last cols1
      , BDCols sig2 cols2 <- List.last lines
      , sig1 == sig2
      -> Just $ BDLines
        [ BDCols sig1 $ List.init cols1 ++ [BDLines $ List.init lines]
        , BDCols sig2 cols2
        ]
    BDCols sig1 cols1@(_ : _)
      | BDLines lines@(_ : _ : _) <- List.last cols1
      , BDEnsureIndent _ (BDCols sig2 cols2) <- List.last lines
      , sig1 == sig2
      -> Just $ BDLines
        [ BDCols sig1 $ List.init cols1 ++ [BDLines $ List.init lines]
        , BDCols sig2 cols2
        ]
    BDPar ind col1@(BDCols sig1 _) col2@(BDCols sig2 _) | sig1 == sig2 ->
      Just $ BDAddBaseY ind (BDLines [col1, col2])
    BDPar ind col1@(BDCols sig1 _) (BDLines (col2@(BDCols sig2 _) : rest))
      | sig1 == sig2 -> Just $ BDPar ind (BDLines [col1, col2]) (BDLines rest)
    BDPar ind (BDLines lines1) col2@(BDCols sig2 _)
      | BDCols sig1 _ <- List.last lines1, sig1 == sig2 -> Just
      $ BDAddBaseY ind (BDLines $ lines1 ++ [col2])
    BDPar ind (BDLines lines1) (BDLines (col2@(BDCols sig2 _) : rest))
      | BDCols sig1 _ <- List.last lines1, sig1 == sig2 -> Just
      $ BDPar ind (BDLines $ lines1 ++ [col2]) (BDLines rest)
    -- BDPar ind1 (BDCols sig1 cols1) (BDPar ind2 line (BDCols sig2 cols2))
    --   | sig1==sig2 ->
    --       Just $ BDPar
    --         ind1
    --         (BDLines [BDCols sig1 cols1, BDCols sig])
    BDCols sig1 cols
      | BDPar _ind line (BDCols sig2 cols2) <- List.last cols, sig1 == sig2
      -> Just
        $ BDLines [BDCols sig1 (List.init cols ++ [line]), BDCols sig2 cols2]
    BDCols sig1 cols
      | BDPar ind line (BDLines lines) <- List.last cols
      , BDCols sig2 cols2 <- List.last lines
      , sig1 == sig2
      -> Just $ BDLines
        [ BDCols sig1
        $ List.init cols
        ++ [BDPar ind line (BDLines $ List.init lines)]
        , BDCols sig2 cols2
        ]
    BDLines [x] -> Just $ x
    BDLines [] -> Just $ BDEmpty
    BDSeq{} -> Nothing
    BDCols{} -> Nothing
    BDSeparator -> Nothing
    BDAddBaseY{} -> Nothing
    BDBaseYPushCur{} -> Nothing
    BDBaseYPop{} -> Nothing
    BDIndentLevelPushCur{} -> Nothing
    BDIndentLevelPop{} -> Nothing
    BDPar{} -> Nothing
    BDAlt{} -> Nothing
    BDForceMultiline{} -> Nothing
    BDForceSingleline{} -> Nothing
    BDForwardLineMode{} -> Nothing
    BDExternal{} -> Nothing
    BDPlain{} -> Nothing
    BDLines{} -> Nothing
    BDAnnotationPrior{} -> Nothing
    BDAnnotationKW{} -> Nothing
    BDAnnotationRest{} -> Nothing
    BDMoveToKWDP{} -> Nothing
    BDEnsureIndent{} -> Nothing
    BDSetParSpacing{} -> Nothing
    BDForceParSpacing{} -> Nothing
    BDDebug{} -> Nothing
    BDNonBottomSpacing _ x -> Just x
  