-----------------------------------------------------------------------------
-- Copyright 2019, Advise-Me project team. This file is distributed under 
-- the terms of the Apache License 2.0. For more information, see the files
-- "LICENSE.txt" and "NOTICE.txt", which are included in the distribution.
-----------------------------------------------------------------------------
-- |
-- Maintainer  :  bastiaan.heeren@ou.nl
-- Stability   :  provisional
-- Portability :  portable (depends on ghc)
--
-----------------------------------------------------------------------------

module Recognize.Data.DiagnoseResult where

import Recognize.Data.Solution
import Recognize.Data.DiagnoseError
import Recognize.Data.Approach
import Recognize.Data.Diagnosis hiding (result)
import Bayes.Evidence
import Recognize.Data.StringLexer
import Recognize.Data.MathParserOutput
import Data.Semigroup
import Util.String
import Ideas.Text.XML
import Ideas.Text.HTML
import Ideas.Text.HTML.W3CSS hiding (tag)
import qualified Text.PrettyPrint.Leijen as PP

data DiagnoseResult = DiagnoseResult
   { originalInput :: Input
   , lexerOutput   :: LexerOutput
   , parserOutput  :: MathParserOutput
   , diagnosis     :: Either DiagnoseError Diagnosis
   , evidence      :: Evidence
   }

instance Show DiagnoseResult where
   show = show . PP.pretty

instance PP.Pretty DiagnoseResult where
   pretty result = PP.vcat
      [ PP.string "Original input"
      , PP.indent 2 (PP.vcat $ map f (getInput (originalInput result)))
      , pp "Lexer output"   $ PP.pretty (lexerOutput result)
      , pp "Parser output"  $ PP.pretty (parserOutput result)
      , pp "Diagnosis"      $ either (PP.string . show) PP.pretty (diagnosis result)
      , pp "Evidence"       $ PP.string $ show (evidence result)
      ]
    where
      pp s a = PP.string (s ++ ":") PP.<$$> PP.indent 2 a
      f = PP.string . either show id

instance HasApproach DiagnoseResult where
  approach = either (Other . strToLower . show) approach . diagnosis

instance ToHTML DiagnoseResult where
   listToHTML = mconcat . map toHTML
   toHTML res = rowsHalf
      ( f inputStr    $ toHTML (originalInput res)
      , f "lexer" $ tag "id" (string "temporarily disabled due to 'invalid name table' error")
      , f "parser" $ w3panel $ tag "id" (string "temporarily disabled due to 'invalid name table' error")
      --, f "lexer"     $ toHTML (lexerOutput res)
      --, f "parser"    $ w3panel $ toHTML (parserOutput res)
      , f "diagnosis" $ toHTML (diagnosis res)
      , f "evidence"  $ w3panel $
           if isEmpty (evidence res) then string "(no evidence)"
           else text (evidence res)
      )
      {-
      )-}
    where
      inputStr = "input " ++ show (getInputId (originalInput res))
      f s body = w3right s <> body

w3panel :: HTMLBuilder -> HTMLBuilder
w3panel xs = panel xs

rowsHalf :: BuildXML a => (a, a, a, a, a) -> a
rowsHalf (x1, x3, x4, x5, x6) = container $
   tag "div" $ rowPadding $ tag "div" (classA "w3-col m6 l7" <> mconcat
   [br, f x1, br, f x3, br, f x5, br]) <>
      tag "div" (classA "w3-col m6 l5" <> mconcat
   [br, f x4, br, f x6, br])
 where
   f x = tag "div" $ card $ background White $ rounded Medium $
            container x

w3right :: String -> HTMLBuilder
w3right s = tag "div" $ bar $ tag "div" $ right $ background LightGray $ small $
   space <> string s <> space

instance ToXML DiagnoseResult where
   toXML result = makeXML "diagnoseresult" $ mconcat
      [ element "originalinput" [builderXML $ originalInput result]
      , element "lexeroutput" [builderXML $ lexerOutput result]
      , element "parseroutput" [builderXML $ parserOutput result]
      , element "diagnosis" [builderXML $ diagnosis result]
      ]