module Article.FeedSources exposing (FeedSources, Source(..), after, before, fromLists, select, selected)

import Article
import Article.Tag as Tag exposing (Tag)
import Username exposing (Username)
import Viewer.Cred as Cred exposing (Cred)



-- TYPES


type FeedSources
    = FeedSources
        { before : List Source
        , selected : Source
        , after : List Source
        }


type Source
    = YourFeed Cred
    | GlobalFeed
    | TagFeed Tag
    | FavoritedFeed Username
    | AuthorFeed Username



-- BUILDING


fromLists : Source -> List Source -> FeedSources
fromLists selectedSource afterSources =
    FeedSources
        { before = []
        , selected = selectedSource
        , after = afterSources
        }



-- SELECTING


select : Source -> FeedSources -> FeedSources
select selectedSource (FeedSources sources) =
    let
        ( newBefore, newAfter ) =
            (sources.before ++ (sources.selected :: sources.after))
                -- By design, tags can only be included if they're selected.
                |> List.filter isNotTag
                |> splitOn (\source -> source == selectedSource)
    in
    FeedSources
        { before = List.reverse newBefore
        , selected = selectedSource
        , after = List.reverse newAfter
        }


splitOn : (Source -> Bool) -> List Source -> ( List Source, List Source )
splitOn isSelected sources =
    let
        ( _, newBefore, newAfter ) =
            List.foldl (splitOnHelp isSelected) ( False, [], [] ) sources
    in
    ( newBefore, newAfter )


splitOnHelp : (Source -> Bool) -> Source -> ( Bool, List Source, List Source ) -> ( Bool, List Source, List Source )
splitOnHelp isSelected source ( foundSelected, beforeSelected, afterSelected ) =
    if isSelected source then
        ( True, beforeSelected, afterSelected )

    else if foundSelected then
        ( foundSelected, beforeSelected, source :: afterSelected )

    else
        ( foundSelected, source :: beforeSelected, afterSelected )


isNotTag : Source -> Bool
isNotTag currentSource =
    case currentSource of
        TagFeed _ ->
            False

        _ ->
            True



-- INFO


selected : FeedSources -> Source
selected (FeedSources record) =
    record.selected


before : FeedSources -> List Source
before (FeedSources record) =
    record.before


after : FeedSources -> List Source
after (FeedSources record) =
    record.after
