-- SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later

module Model.Rating where

import ClassyPrelude.Yesod
import Model
import CryptoID
-- import Data.Text (Text)
import Data.Text.Encoding.Error (UnicodeException(..))

import Data.Aeson.TH
import Utils.PathPiece


data Rating = Rating
  { ratingCourseTerm :: TermIdentifier
  , ratingCourseSchool :: SchoolName
  , ratingCourseName :: CourseName
  , ratingSheetName :: SheetName
  , ratingCorrectorName :: Maybe Text
  , ratingSheetType :: SheetType RatingExamPartReference
  , ratingValues :: Rating'
  } deriving (Read, Show, Eq, Generic)
    deriving anyclass (NFData)

data RatingExamPartReference = RatingExamPartReference
  { ratingExamName :: ExamName
  , ratingExamPartNumber :: ExamPartNumber
  } deriving (Read, Show, Eq, Ord, Generic)
    deriving anyclass (NFData)

data Rating' = Rating'
  { ratingPoints :: Maybe Points
  , ratingComment :: Maybe Text
  , ratingTime :: Maybe UTCTime
  , ratingDone :: Bool
  } deriving (Read, Show, Eq, Generic)
    deriving anyclass (NFData)

deriveJSON defaultOptions
  { fieldLabelModifier = camelToPathPiece' 1
  } ''RatingExamPartReference


data RatingValidityException
  = RatingNegative       -- ^ Rating points must be non-negative
  | RatingExceedsMax     -- ^ Rating point must not exceed maximum points
  | RatingNotExpected    -- ^ Rating not expected
  | RatingBinaryExpected -- ^ Rating must be 0 or 1
  | RatingPointsRequired -- ^ Rating without points for sheet that requires there to be points
  deriving (Show, Eq, Generic)
  deriving anyclass (Exception)

data RatingParseLegacyException
  = RatingNotUnicode UnicodeException -- ^ Rating failed to parse as unicode
  | RatingMissingSeparator            -- ^ Could not split rating header from comments
  | RatingMultiple                    -- ^ Encountered multiple point values in rating
  | RatingInvalid Text                -- ^ Failed to parse rating point value
  deriving (Show, Eq, Generic)
  deriving anyclass (Exception)

data RatingParseException
  = RatingYAMLStreamTerminatedUnexpectedly
  | RatingYAMLDocumentEndIllDefined
  | RatingYAMLExceptionBeforeComment String -- ^ Could not parse YAML to determine where rating comments begin
  | RatingYAMLException String -- ^ Could not parse YAML
  | RatingYAMLCommentNotUnicode UnicodeException
  | RatingYAMLNotUnicode String
  deriving (Show, Eq, Generic)
  deriving anyclass (Exception)

data RatingException
  = RatingFileIsDirectory             -- ^ We do not expect this to happen, it's included for totality
  | RatingSubmissionIDIncorrect
  | RatingParseException RatingParseException
  | RatingParseLegacyException RatingParseLegacyException
  | RatingValidityException RatingValidityException
  deriving (Show, Eq, Generic)
  deriving anyclass (Exception)

data RatingFileException
  = RatingFileException
    { ratingExceptionFile :: FilePath
    , ratingException :: RatingException
    }
  | RatingSubmissionException
    { ratingExceptionSubmission :: CryptoFileNameSubmission
    , ratingException :: RatingException
    }
  deriving (Show, Eq, Generic)
  deriving anyclass (Exception)
