{-# LANGUAGE DeriveGeneric, DeriveAnyClass #-}
module Eventloop.Module.BasicShapes.Types
    ( module Eventloop.Module.BasicShapes.Types
    , CanvasId
    , Alignment(..)
    ) where

import Eventloop.Module.Websocket.Canvas.Types (CanvasId, Alignment(..))
import Eventloop.Utility.Vectors

import GHC.Generics (Generic)
import Control.DeepSeq


type GraphicalNumeric = Float
type Position = Point

type Width = GraphicalNumeric
type Height = GraphicalNumeric
type Dimensions = (Width, Height)

type Radius = GraphicalNumeric

type Red = GraphicalNumeric
type Green = GraphicalNumeric
type Blue = GraphicalNumeric
type Alpha = GraphicalNumeric
type Color = (Red, Green, Blue, Alpha)
type FillColor = Color
type StrokeColor = Color

type FillThickness = GraphicalNumeric
type StrokeLineThickness = GraphicalNumeric

type UpperLeft = Point
type UpperRight = Point
type LowerLeft = Point
type LowerRight = Point

type NumberOfPoints = Int

type FontFamily = [Char]
type FontSize = GraphicalNumeric


data BasicShapesOut = DrawShapes CanvasId [Shape]
                    deriving (Show, Eq, Generic, NFData)

data Shape = CompositeShape { shapes :: [Shape]
                            , positionM :: Maybe Position
                            , rotationM :: Maybe Rotation
                            } -- ^Should contain atleast 1 shape. Rotation before Position
           | Rectangle { position :: Position
                       , dimensions :: Dimensions
                       , fillColor :: FillColor
                       , strokeLineThickness :: StrokeLineThickness
                       , strokeColor :: StrokeColor
                       , rotationM :: Maybe Rotation
                       } -- ^| Position is upperleftcorner. Position is the corner closes to origin. Visually in canvas, this is top left. In a Cartesian coördinate system, this is bottom left.
           | Circle { position :: Position
                    , radius :: Radius
                    , fillColor :: FillColor
                    , strokeLineThickness :: StrokeLineThickness
                    , strokeColor :: StrokeColor
                    , rotationM :: Maybe Rotation
                    } -- ^| Position is center
           | RegularPolygon { position :: Position
                     , numberOfPoints :: NumberOfPoints
                     , radius :: Radius
                     , fillColor :: FillColor
                     , strokeLineThickness :: StrokeLineThickness
                     , strokeColor :: StrokeColor
                     , rotationM :: Maybe Rotation
                     } -- ^The first point of the regular polygon, always starts in the direction from the x-axis.(Towards x-infinity). Position is the the centre of the regular polygon
           | Text { text :: [Char]
                  , fontFamily :: FontFamily
                  , fontSize :: FontSize
                  , position :: Position
                  , alignment :: Alignment
                  , fillColor :: FillColor
                  , strokeLineThickness :: StrokeLineThickness
                  , strokeColor :: StrokeColor
                  , rotationM :: Maybe Rotation
                  }
           | Line { point1 :: Point
                  , point2 :: Point
                  , strokeLineThickness :: StrokeLineThickness
                  , strokeColor :: StrokeColor
                  , rotationM :: Maybe Rotation
                  }
           | MultiLine { points :: [Point] -- ^| Can contain any number of points
                       , strokeLineThickness :: StrokeLineThickness
                       , strokeColor :: StrokeColor
                       , rotationM :: Maybe Rotation
                       }
           | FilledMultiLine { points :: [Point]
                             , fillWidth :: FillThickness
                             , fillColor :: FillColor
                             , strokeLineThickness :: StrokeLineThickness
                             , strokeColor :: StrokeColor
                             , rotationM :: Maybe Rotation
                             }
           | Polygon { points :: [Point] -- ^| Closes shape automatically with fill. Do not forget that the fill encloses the entire path. This means that half of the stroke is overwritten by the fill.
                     , fillColor :: FillColor
                     , strokeLineThickness :: StrokeLineThickness
                     , strokeColor :: StrokeColor
                     , rotationM :: Maybe Rotation
                     }
           deriving (Show, Eq, Generic, NFData)


data Rotation = Rotation RotatePoint Angle -- ^| Rotation is around a point on the canvas. May be the centre of the boundingbox (enclosing rectangle) or an arbitrary point. Angle is in degrees and counter-clockwise in the coördinate system(from the x-axis to the y-axis) and visually on canvas clock-wise.
            deriving (Show, Eq, Generic, NFData)

data RotatePoint = AroundCenter
                 | AroundPoint Point
                deriving (Show, Eq, Generic, NFData)

data BoundingBox = BoundingBox LowerLeft UpperLeft UpperRight LowerRight -- ^| The point indications are from the perspective of a regular Cartesian coördinate system.
                deriving (Show, Eq)