module Pages.Debate.Arguments exposing (Model, Msg, page)

import Browser.Events as Events
import Config.Data.Identity exposing (pageNames)
import Config.Data.ImageFolders as M
    exposing
        ( ImageFolder(..)
        , imagePathMaker
        )
import Config.Helpers.Cards.Inner.StrengthBar exposing (barMaker)
import Config.Helpers.Cards.Inner.Text
    exposing
        ( bodyFormat
        , detailBodyLink
        , detailBodyMaker
        , detailFormat
        , detailSpacing
        , detailTitleMaker
        , generalButton
        , getHoverColours
        )
import Config.Helpers.Cards.Inner.ToolTip
    exposing
        ( ToolTipPosition(..)
        , tooltip
        )
import Config.Helpers.Cards.Outer.Helpers exposing (cardMaker)
import Config.Helpers.Cards.Outer.Types as C exposing (Cardable(..))
import Config.Helpers.Converters exposing (formatName, toTitleCase)
import Config.Helpers.Headers.Helpers exposing (headerMaker)
import Config.Helpers.Headers.Records exposing (argumentHeader)
import Config.Helpers.Headers.Types as R exposing (Headerable(..))
import Config.Helpers.Response
    exposing
        ( pageList
        , topLevelContainer
        )
import Config.Helpers.Viewport exposing (resetViewport)
import Config.Pages.Debate.Arguments.List
    exposing
        ( argumentList
        )
import Config.Pages.Debate.Arguments.Types exposing (Argument)
import Config.Style.Colour.Helpers
    exposing
        ( ThemeColor(..)
        , getThemeColor
        )
import Config.Style.Icons.Icons
    exposing
        ( code
        , copyLink
        , thumbsDown
        )
import Config.Style.Icons.Types as TySvg
    exposing
        ( InnerPart
        , OuterPart
        )
import Config.Style.Images
    exposing
        ( ElementSize(..)
        , imageSquareMaker
        )
import Config.Style.Transitions exposing (transitionStyleSlow)
import Effect exposing (Effect)
import Element as E
    exposing
        ( Attribute
        , Device
        , DeviceClass(..)
        , Element
        , Orientation(..)
        , alignLeft
        , alignRight
        , alignTop
        , centerX
        , centerY
        , clip
        , column
        , el
        , fill
        , focused
        , height
        , htmlAttribute
        , maximum
        , none
        , paddingEach
        , paddingXY
        , paragraph
        , rgba
        , row
        , spacing
        , text
        , width
        )
import Element.Background as B exposing (color)
import Element.Border as D
    exposing
        ( color
        , rounded
        , shadow
        )
import Element.Font as F
    exposing
        ( bold
        , center
        , color
        )
import Element.Input as Input
import Html.Attributes as H exposing (style)
import Layouts
import Page exposing (Page)
import Ports
import Process
import Route exposing (Route)
import Route.Path as Path
import Shared
import Svg.Attributes as SvgAttr
import Task
import View exposing (View)


page : Shared.Model -> Route () -> Page Model Msg
page shared route =
    Page.new
        { init = init
        , update = update
        , subscriptions = subscriptions
        , view = view shared
        }
        |> Page.withLayout toLayout


toLayout : Model -> Layouts.Layout Msg
toLayout model =
    Layouts.Navbar {}



-- INIT


type alias Model =
    { hasBeenCopied : List Bool }


init : () -> ( Model, Effect Msg )
init () =
    ( { hasBeenCopied = List.repeat (List.length argumentList) False }
    , Effect.batch
        [ Effect.map
            (\_ -> NoOp)
            (Effect.sendCmd resetViewport)
        , Effect.none
        ]
    )



-- UPDATE


type Msg
    = CopyText String Int
    | ResetCopyState Int
    | NoOp


update : Msg -> Model -> ( Model, Effect Msg )
update msg model =
    let
        urlLinkClickUpdate : Int -> Model
        urlLinkClickUpdate index =
            { model
                | hasBeenCopied =
                    List.take index model.hasBeenCopied
                        ++ (case List.head (List.drop index model.hasBeenCopied) of
                                Just isCLicked ->
                                    [ not isCLicked ]

                                Nothing ->
                                    []
                            -- shouldn't happen
                           )
                        ++ List.drop (index + 1) model.hasBeenCopied
            }
    in
    case msg of
        CopyText text index ->
            ( urlLinkClickUpdate index
            , Effect.batch
                [ Effect.sendCmd (Ports.copyToClipboard text)
                , Effect.sendCmd (Process.sleep 700 |> Task.perform (\_ -> ResetCopyState index))
                ]
            )

        ResetCopyState index ->
            ( urlLinkClickUpdate index
              -- wrong lol
            , Effect.none
            )

        NoOp ->
            ( model
            , Effect.none
            )



-- SUBSCRIPTIONS


subscriptions : Model -> Sub Msg
subscriptions model =
    Sub.none



-- VIEW


view : Shared.Model -> Model -> View Msg
view shared model =
    { title = "debate (" ++ pageNames.pageArguments ++ ")"
    , attributes = []
    , element = debateContainer shared model
    }


debateContainer : Shared.Model -> Model -> Element Msg
debateContainer shared model =
    topLevelContainer (debateList shared model)


debateList : Shared.Model -> Model -> Element Msg
debateList shared model =
    column
        (case ( shared.device.class, shared.device.orientation ) of
            _ ->
                pageList shared.device
        )
    <|
        List.concat
            [ [ headerMaker (R.Arguments argumentHeader) ]
            , List.map3
                (\argument dummy index ->
                    cardMaker shared.device
                        (C.Argument argument)
                        (contentList shared model dummy index argument)
                )
                argumentList
                model.hasBeenCopied
                (List.range 0 (List.length argumentList))
            ]


contentList : Shared.Model -> Model -> Bool -> Int -> Argument -> List (Element Msg)
contentList shared model isLinkClicked index argument =
    let
        image : ElementSize -> Element msg
        image size =
            el
                [ alignLeft
                , alignTop
                , paddingEach
                    { top = 0
                    , right = 10
                    , bottom = 0
                    , left = 0
                    }
                ]
            <|
                imageSquareMaker shared.device (imagePathMaker M.Argument argument.argumentImage) True size
    in
    [ row
        [ width fill
        , paddingEach
            { top =
                case ( shared.device.class, shared.device.orientation ) of
                    ( Phone, Portrait ) ->
                        8

                    ( Tablet, Portrait ) ->
                        8

                    _ ->
                        0
            , right = 0
            , bottom = 0
            , left = 0
            }
        ]
        [ detailFormat column
            [ detailFormat paragraph
                [ case ( shared.device.class, shared.device.orientation ) of
                    ( Phone, Portrait ) ->
                        none

                    ( Tablet, Portrait ) ->
                        none

                    _ ->
                        image Medium
                , el ([ height fill ] ++ bodyFormat TextLightGrey) <| text argument.propositionSummary
                ]
            , detailFormat row
                [ strengthMaker shared
                , barMaker shared getConfidenceTooltip argument.argumentCertainty
                ]
            ]
        ]
    , tableMaker shared.device argument
    , formalizationMaker shared.device argument
    , el [ alignRight ] <|
        row [ width fill, spacing 20 ]
            [ generalButton shared (Path.toString Path.Contact_Criticism) thumbsDown
            , generalButton shared argument.proofLink code
            , copyButton shared model isLinkClicked index argument
            ]
    ]


copyButton : Shared.Model -> Model -> Bool -> Int -> Argument -> Element Msg
copyButton shared model isLinkClicked index argument =
    Input.button
        [ focused
            [ D.color (rgba 0 0 0 0)
            , D.shadow
                { blur = 0
                , color = rgba 0 0 0 0
                , offset = ( 0, 0 )
                , size = 0
                }
            ]
        ]
        { onPress = Just (CopyText ("https://uprootnutrition.com" ++ Path.toString Path.Debate_Arguments ++ "#" ++ formatName argument.argumentImage) index)
        , label =
            el
                (if isLinkClicked then
                    [ transitionStyleSlow
                    , tooltip IsRight "Copied!"
                    , case ( shared.device.class, shared.device.orientation ) of
                        ( Phone, Portrait ) ->
                            B.color (getThemeColor BackgroundDarkGrey)

                        ( Tablet, Portrait ) ->
                            B.color (getThemeColor BackgroundDarkGrey)

                        _ ->
                            B.color (getThemeColor BackgroundDeepDarkGrey)
                    , paddingXY 7 7
                    , D.rounded 10
                    , F.color (getThemeColor TextLightOrange)
                    ]

                 else
                    [ transitionStyleSlow
                    , B.color (getThemeColor Transparent)
                    , paddingXY 7 7
                    , D.rounded 10
                    , F.color (getThemeColor TextLightOrange)
                    ]
                        ++ getHoverColours TextLightOrange
                )
            <|
                copyLink
                    { elementAttributes =
                        []
                    , sharedModel = shared
                    , svgAttributes = [ SvgAttr.width "20" ]
                    }
        }


strengthMaker : Shared.Model -> Element msg
strengthMaker shared =
    el
        (case ( shared.device.class, shared.device.orientation ) of
            ( Phone, Portrait ) ->
                []

            ( Tablet, Portrait ) ->
                []

            _ ->
                if not shared.isNavbarExpanded then
                    [ tooltip IsLeft
                        "This represents how dope I think the inference/reductio is."
                    ]

                else
                    []
        )
    <|
        detailTitleMaker TextLightOrange "Banger Rating:"


getConfidenceTooltip : Int -> String
getConfidenceTooltip num =
    case num of
        0 ->
            "Extremely low. Highly speculative."

        1 ->
            "Very low. Almost entirely uncertain."

        2 ->
            "Low. Highly uncertain."

        3 ->
            "Kinda low. More uncertain than not."

        4 ->
            "Below average. Some significant doubts."

        5 ->
            "Moderate. Equal mix of certainty and doubt."

        6 ->
            "Above average. More certain than not."

        7 ->
            "Kinda high. Fairly confident."

        8 ->
            "High. Strongly confident."

        9 ->
            "Very high. Almost entirely certain."

        10 ->
            "Extremely high. Completely certain."

        _ ->
            "Confidence level out of expected range."


tableMaker : Device -> Argument -> Element msg
tableMaker device argument =
    let
        cellPadding : Attribute msg
        cellPadding =
            paddingXY 10 5
    in
    column
        [ centerX
        , E.width fill
        ]
        [ el
            [ E.width fill
            , htmlAttribute <| H.style "position" "relative"
            ]
          <|
            E.table
                ([ D.rounded 10
                 , D.width 2
                 , D.color (getThemeColor TextDarkGrey)
                 , clip
                 ]
                    ++ (case ( device.class, device.orientation ) of
                            ( Phone, Portrait ) ->
                                [ B.color (getThemeColor BackgroundSpreadsheet) ]

                            ( Tablet, Portrait ) ->
                                [ B.color (getThemeColor BackgroundSpreadsheet) ]

                            _ ->
                                []
                       )
                )
                { data = argument.definitionTable
                , columns =
                    [ { header =
                            el
                                [ F.bold
                                , D.widthEach
                                    { bottom = 1
                                    , top = 1
                                    , left = 1
                                    , right = 1
                                    }
                                , D.color (getThemeColor TextDarkGrey)
                                , cellPadding
                                , E.width fill
                                ]
                            <|
                                detailTitleMaker
                                    TextLightOrange
                                    "Definiendum"
                      , width = fill |> maximum 30
                      , view =
                            \definition ->
                                el
                                    [ D.widthEach
                                        { bottom = 1
                                        , top = 0
                                        , left = 1
                                        , right = 1
                                        }
                                    , D.color (getThemeColor TextDarkGrey)
                                    , cellPadding
                                    , E.height fill
                                    ]
                                <|
                                    el
                                        [ centerX
                                        , centerY
                                        ]
                                    <|
                                        paragraph [] [ detailTitleMaker TextLightOrange definition.definiendum ]
                      }
                    , { header =
                            el
                                [ D.widthEach
                                    { bottom = 1
                                    , top = 1
                                    , left = 0
                                    , right = 1
                                    }
                                , D.color (getThemeColor TextDarkGrey)
                                , cellPadding
                                , E.width fill
                                ]
                            <|
                                detailTitleMaker TextLightOrange "Definiens"
                      , width = fill
                      , view =
                            \definition ->
                                el
                                    [ D.widthEach
                                        { bottom = 1
                                        , top = 0
                                        , left = 0
                                        , right = 1
                                        }
                                    , D.color (getThemeColor TextDarkGrey)
                                    , cellPadding
                                    , E.height fill
                                    ]
                                <|
                                    el [] <|
                                        paragraph [] [ detailBodyMaker TextLightGrey (text definition.definiens) ]
                      }
                    ]
                }
        ]


formalizationMaker : Device -> Argument -> Element msg
formalizationMaker device argument =
    column
        [ centerX
        , E.width fill
        , spacing 10
        ]
        (List.indexedMap
            (\index argumentEntry ->
                column
                    [ paddingXY
                        (case ( device.class, device.orientation ) of
                            ( Phone, Portrait ) ->
                                0

                            ( Tablet, Portrait ) ->
                                0

                            _ ->
                                40
                        )
                        3
                    ]
                    (List.indexedMap
                        (\entryIndex entryWithNotation ->
                            column
                                [ centerX
                                , F.center
                                , detailSpacing
                                , E.width fill
                                ]
                                [ paragraph
                                    [ width fill ]
                                    [ detailTitleMaker
                                        TextLightOrange
                                        (if entryIndex < List.length argumentEntry.premises then
                                            "P" ++ String.fromInt (entryIndex + 1) ++ ") "

                                         else
                                            "C) "
                                        )
                                    , detailBodyMaker TextLightGrey
                                        (text
                                            (if entryIndex < List.length argumentEntry.premises then
                                                entryWithNotation.premise

                                             else
                                                argumentEntry.conclusion
                                            )
                                        )
                                        |> el
                                            []
                                    ]
                                , paragraph
                                    []
                                    [ detailTitleMaker
                                        TextLightOrange
                                        (if entryIndex < List.length argumentEntry.premises then
                                            "(" ++ entryWithNotation.notation ++ ")"

                                         else
                                            "(∴" ++ argumentEntry.conclusionNotation ++ ")"
                                        )
                                    ]
                                ]
                        )
                        (argumentEntry.premises ++ [ { premise = argumentEntry.conclusion, notation = argumentEntry.conclusionNotation } ])
                    )
            )
            argument.argumentFormalization
        )
