module Zipper exposing (..)

import List exposing ((::))


type Zipper a
    = Zipper (List a) a (List a)


fromList : List a -> Maybe (Zipper a)
fromList list =
    case list of
        x :: xs ->
            Just <| Zipper [] x xs

        _ ->
            Nothing


toList : Zipper a -> List a
toList (Zipper l f r) =
    List.reverse l ++ f :: r


moveLeft : Zipper a -> Zipper a
moveLeft z =
    case z of
        Zipper (l :: ls) f rs ->
            Zipper ls l (f :: rs)

        _ ->
            z


moveRight : Zipper a -> Zipper a
moveRight z =
    case z of
        Zipper ls f (r :: rs) ->
            Zipper (f :: ls) r rs

        _ ->
            z


length : Zipper a -> Int
length (Zipper ls _ rs) =
    List.length ls + 1 + List.length rs


position : Zipper a -> Int
position (Zipper ls _ _) =
    List.length ls


left : Zipper a -> List a
left (Zipper ls _ _) =
    ls


right : Zipper a -> List a
right (Zipper _ _ rs) =
    rs


hasLeft : Zipper a -> Bool
hasLeft (Zipper ls _ _) =
    not <| List.isEmpty ls


hasRight : Zipper a -> Bool
hasRight (Zipper _ _ rs) =
    not <| List.isEmpty rs


focus : Zipper a -> a
focus (Zipper _ f _) =
    f
