module AdvSearch.Tags exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Set
import Dict
import Lib.Autocomplete as A
import Lib.Html exposing (..)
import Lib.Util exposing (..)
import Gen.Api as GApi
import AdvSearch.Lib exposing (..)
import AdvSearch.Set as S
type alias Model =
{ sel : S.Model (Int,Int) -- Tag, Level
, conf : A.Config Msg GApi.ApiTagResult
, search : A.Model GApi.ApiTagResult
, spoiler : Int
, inherit : Bool
, exclie : Bool
}
type Msg
= Sel (S.Msg (Int,Int))
| Level (Int,Int) Int
| Spoiler
| Inherit Bool
| ExcLie Bool
| Search (A.Msg GApi.ApiTagResult)
init : Data -> (Data, Model)
init dat =
let (ndat, sel) = S.init dat
in ( { ndat | objid = ndat.objid + 1 }
, { sel = { sel | single = False, and = True }
, conf = { wrap = Search, id = "xsearch_tag" ++ String.fromInt ndat.objid, source = A.tagSource }
, search = A.init ""
, spoiler = dat.defaultSpoil
, inherit = True
, exclie = False
}
)
update : Data -> Msg -> Model -> (Data, Model, Cmd Msg)
update dat msg model =
case msg of
Sel m -> (dat, { model | sel = S.update m model.sel }, Cmd.none)
Level (t,ol) nl -> (dat, { model | sel = S.update (S.Sel (t,ol) False) model.sel |> S.update (S.Sel (t,nl) True) }, Cmd.none)
Spoiler -> (dat, { model | spoiler = if model.spoiler < 2 then model.spoiler + 1 else 0, exclie = False }, Cmd.none)
Inherit b -> (dat, { model | inherit = b }, Cmd.none)
ExcLie b -> (dat, { model | exclie = b }, Cmd.none)
Search m ->
let (nm, c, res) = A.update model.conf m model.search
in case res of
Nothing -> (dat, { model | search = nm }, c)
Just t ->
( { dat | tags = Dict.insert t.id t dat.tags }
, { model | search = A.clear nm "", sel = S.update (S.Sel (vndbidNum t.id,0) True) model.sel }
, c )
toQuery m = S.toQuery (\o (t,l) ->
let id = if m.inherit then 8 else 14
in if m.spoiler == 0 && not m.exclie && l == 0 then QInt id o t else QTuple id o t ((if m.exclie then 16*3 else 0) + l*3 + m.spoiler)) m.sel
fromQuery spoil inherit exclie dat q =
let id = if inherit then 8 else 14
f qr = case qr of
QInt x op t -> if id == x && spoil == 0 && not exclie then Just (op, (t,0)) else Nothing
QTuple x op t v -> if id == x && modBy 3 v == spoil && exclie == ((v // (16*3)) == 1) then Just (op, (t, modBy 16 (v//3))) else Nothing
_ -> Nothing
in
S.fromQuery f dat q |> Maybe.map (\(ndat,sel) ->
( { ndat | objid = ndat.objid+1 }
, { sel = { sel | single = False, and = sel.and || Set.size sel.sel == 1 }
, conf = { wrap = Search, id = "xsearch_tag" ++ String.fromInt ndat.objid, source = A.tagSource }
, search = A.init ""
, spoiler = spoil
, inherit = inherit
, exclie = exclie
}
))
view : Data -> Model -> (Html Msg, () -> List (Html Msg))
view dat model =
( case Set.toList model.sel.sel of
[] -> small [] [ text "Tags" ]
[(s,_)] -> span [ class "nowrap" ]
[ S.lblPrefix model.sel
, small [] [ text <| "g" ++ String.fromInt s ++ ":" ]
, Dict.get (vndbid 'g' s) dat.tags |> Maybe.map (\t -> t.name) |> Maybe.withDefault "" |> text
]
l -> span [] [ S.lblPrefix model.sel, text <| "Tags (" ++ String.fromInt (List.length l) ++ ")" ]
, \() ->
[ div [ class "advheader" ]
[ h3 [] [ text "Tags" ]
, div [ class "opts" ]
[ Html.map Sel (S.optsMode model.sel True False)
, a [ href "#", onClickD Spoiler ]
[ text <| if model.spoiler == 0 then "no spoilers" else if model.spoiler == 1 then "minor spoilers" else "major spoilers" ]
, linkRadio model.sel.neg (Sel << S.Neg) [ text "invert" ]
]
, div [ class "opts" ]
[ if model.spoiler < 2 then span [] [] else
linkRadio model.exclie ExcLie [ text "exclude lies" ]
, linkRadio model.inherit Inherit [ text "child tags" ]
]
]
, ul [] <| List.map (\(t,l) ->
li [ style "overflow" "hidden", style "text-overflow" "ellipsis" ]
[ inputButton "X" (Sel (S.Sel (t,l) False)) []
, inputSelect "" l (Level (t,l)) [style "width" "60px"] <|
(0, "any")
:: List.map (\i -> (i, String.fromInt (i//5) ++ "." ++ String.fromInt (2*(modBy 5 i)) ++ "+")) (List.range 1 14)
++ [(15, "3.0")]
, small [] [ text <| " g" ++ String.fromInt t ++ ": " ]
, Dict.get (vndbid 'g' t) dat.tags |> Maybe.map (\e -> a [ href ("/" ++ e.id), target "_blank", style "display" "inline" ] [ text e.name ]) |> Maybe.withDefault (text "")
]
) (Set.toList model.sel.sel)
, A.view model.conf model.search [ placeholder "Search..." ]
]
)