{-# LANGUAGE CPP                        #-}
{-# LANGUAGE Safe                       #-}
{-# LANGUAGE PolyKinds                  #-}
{-# LANGUAGE ConstraintKinds            #-}
{-# LANGUAGE DefaultSignatures          #-}
{-# LANGUAGE DeriveFunctor              #-}
{-# LANGUAGE DeriveGeneric              #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE FlexibleInstances          #-}
--{-# LANGUAGE RebindableSyntax           #-}
{-# LANGUAGE TypeOperators              #-}
{-# LANGUAGE TypeFamilies               #-}
{-# LANGUAGE RankNTypes               #-}

{-# LANGUAGE DataKinds               #-}

module Data.Algebra.Geometric where

import safe Data.Algebra
import safe Data.Algebra.Dual
import safe Data.Algebra.Split
import safe Data.Distributive
import safe Data.Functor.Classes
import safe Data.Functor.Compose
import safe Data.Functor.Rep
import safe Data.Semifield
import safe Data.Semigroup.Foldable
import safe Data.Semimodule hiding (Basis)
import safe Data.Semimodule.Free
import safe Data.Semimodule.Basis
import safe Data.Semimodule.Transform
import safe Data.Semiring
import safe GHC.Generics hiding (Rep, C, D)
import safe Prelude hiding (Num(..), Fractional(..), Real, sum, product)

import Data.Functor.Product
import Data.Complex


type C = Complex

type Comp a = Real a => Complex a



{-
-- See < https://en.wikipedia.org/wiki/Classification_of_Clifford_algebras#Classification >
--
type family Basis (f :: * -> *) :: * where

  -- | Clifford algebras on two real dimensions
  Basis S = CB1 Cl10
  Basis C = CB1 Cl01

  -- | Clifford algebras on four real dimensions
  Basis (V2**V2) = CB2 Cl20
  Basis (V2**V2) = CB2 Cl11
  Basis H = CB2 Cl02

  -- | Clifford algebras on eight real dimensions
  Basis (V2**V2**C) = CB3 Cl30
  Basis (V2**V2**S) = CB3 Cl21
  Basis (H**C) = CB3 Cl12
  Basis (H**S) = CB3 Cl03

  -- | Clifford algebras on sixteen real dimensions
  Basis (V2**V2**H) = CB4 Cl40
  Basis (V4**V4) = CB4 Cl31
  Basis (V4**V4) = CB4 Cl22
  Basis (V2**V2**H) = CB4 Cl13
  Basis (V2**V2**H) = CB4 Cl04

(E2,E2,D2
-- | Kinds for real clifford algebras
--
data Cl0 = Cl00
data Cl1 = Cl10 | Cl01 -- Clifford algebras on two real dimensions
data Cl2 = Cl20 | Cl11 | Cl02
data Cl3 = Cl30 | Cl21 | Cl12 | Cl03
data Cl4 = Cl40 | Cl31 | Cl22 | Cl13 | Cl04

newtype CB1 (cl :: Cl1) = CB1 B1 
newtype CB2 (cl :: Cl2) = CB2 B2
newtype CB3 (cl :: Cl3) = CB3 B3
newtype CB4 (cl :: Cl4) = CB4 B4

-}

{-

TODO:
  add ++, ** to Transform
  update Mij types, matrices to use compose
  add basis stuff to Basis
  update all basis representations & Algebra instances
  break out Geometric module
  
class Clifford a b => Geometric1 a b where
  geom1 :: Tran a b B1



-}


-- Clifford bases, broken out by < https://en.wikipedia.org/wiki/Blade_(geometry) blade >.
data B0 = B0
data B1 = B10 | B11
data B2 = B20 | B21 E2 | B22
data B3 = B30 | B31 E3 | B32 E3 | B33
data B4 = B40 | B41 E4 | B42 E6 | B43 E4 | B44




{-
--newtype Biquat r = Biquat (Quat r) deriving Show
--type Biquat = Compose H
--type SH r = (Split—Biquat) r
--type DH r = (Dual—Biquat) r

type Bi = Complex
-- | < https://en.wikipedia.org/wiki/Bicomplex_number >
-- type Bicomplex r = Product C C r
type Bicomplex r = (Bi++Complex) r

-- | < https://en.wikipedia.org/wiki/Biquaternion >
--type Biquat r = Compose H C r -- == M22 (C r)

-- | < https://en.wikipedia.org/wiki/Dual_quaternion >
type DualBiquat r = Compose H Dual r

-- | < https://en.wikipedia.org/wiki/Split-biquaternion >
type SplitBiquat r = Compose H Split r


type S = Split
type D = Dual
type C = Complex
type H = Quat
type DH = Compose H Dual

-}