module Signals exposing (..)

import Card exposing (CardData, ManaColor(..))
import Database exposing (Database)
import Draft exposing (Draft, Pick)
import List.Extra as List
import Zipper


type alias CardsSeenPerColor =
    { white : Int
    , blue : Int
    , black : Int
    , red : Int
    , green : Int
    }


inferSignalCounts : Bool -> Database -> Draft -> List ( Int, CardsSeenPerColor )
inferSignalCounts includeWholeDeck db draft =
    let
        numberOfPicks =
            if includeWholeDeck then
                Zipper.length draft

            else
                List.length (Zipper.left draft) + 1

        relevantPicks =
            List.take numberOfPicks (Zipper.toList draft)
    in
    List.range 0 (numberOfPicks - 1)
        |> List.map (\i -> ( i, countCardsInPicks db (List.take (i + 1) relevantPicks) ))


type alias CardsSeenPerColorDelta =
    { white : Float
    , blue : Float
    , black : Float
    , red : Float
    , green : Float
    }


inferSignalDelta : Bool -> Database -> Draft -> List ( Int, CardsSeenPerColorDelta )
inferSignalDelta includeWholeDeck db draft =
    let
        numberOfPicks =
            Zipper.length draft

        expectedCountPerPick =
            List.range 0 (numberOfPicks - 1) |> List.map expectedCardsSeenPerColor
    in
    List.zip (inferSignalCounts includeWholeDeck db draft) expectedCountPerPick
        |> List.map
            (\( ( pickNumber, cardsSeen ), expectedCount ) ->
                ( pickNumber
                , { white = toFloat cardsSeen.white - expectedCount
                  , blue = toFloat cardsSeen.blue - expectedCount
                  , black = toFloat cardsSeen.black - expectedCount
                  , red = toFloat cardsSeen.red - expectedCount
                  , green = toFloat cardsSeen.green - expectedCount
                  }
                )
            )


expectedCardsSeen : Int -> Int
expectedCardsSeen pickNumber =
    if pickNumber == 0 then
        14

    else
        (14 - modBy 14 pickNumber) + expectedCardsSeen (pickNumber - 1)


expectedCardsSeenPerColor : Int -> Float
expectedCardsSeenPerColor pickNumber =
    toFloat (expectedCardsSeen pickNumber) / 5.0


countCardsInPicks : Database -> List Pick -> CardsSeenPerColor
countCardsInPicks db picks =
    let
        allCards =
            allCardsInPicks db picks

        countColor color =
            List.count (\card -> List.member color card.details.colors) allCards
    in
    { white = countColor White
    , blue = countColor Blue
    , black = countColor Black
    , red = countColor Red
    , green = countColor Green
    }


allCardsInPicks : Database -> List Pick -> List CardData
allCardsInPicks db picks =
    let
        cardsPicked =
            List.concatMap .available picks
    in
    List.filterMap (\pick -> Database.get pick.name db) cardsPicked
