---------------------------------------------------------------------------------------------------
-- |
-- Module      : Classification
-- Description : Types for simple and semisimple Lie Algebras
-- Copyright   : (c) Felix Springer, 2019
-- License     : BSD3
-- Maintainer  : felixspringer149@gmail.com
-- Stability   : experimental
-- Portability : POSIX
--
-- This module represents the classified simple and semisimple Lie Algebras.
--
---------------------------------------------------------------------------------------------------

module Lie.Classification ( Simple (..)
                          , SemiSimple (..)
                          ) where

import Data.List (sortBy)

data Simple = A Int
            | B Int
            | C Int
            | D Int
            | E6 | E7 | E8
            | F4
            | G2

instance Eq Simple where
  (==) (A n) (A m) = n == m
  (==) (B n) (B m) = n == m
  (==) (C n) (C m) = n == m
  (==) (D n) (D m) = n == m
  (==)  E6    E6   = True
  (==)  E7    E7   = True
  (==)  E8    E8   = True
  (==)  F4    F4   = True
  (==)  G2    G2   = True
  (==) (A 3) (D 3) = True
  (==) (D 3) (A 3) = True
  (==) (B 3) (C 3) = True
  (==) (C 3) (B 3) = True
  (==) _     _     = False

instance Show Simple where
  show (A n) = wordIndex "A" n
  show (B n) = wordIndex "B" n
  show (C n) = wordIndex "C" n
  show (D n) = wordIndex "D" n
  show  E6   = wordIndex "E" 6
  show  E7   = wordIndex "E" 7
  show  E8   = wordIndex "E" 8
  show  F4   = wordIndex "F" 4
  show  G2   = wordIndex "G" 2

wordIndex :: String -> Int -> String
wordIndex word n = word ++ indexSub n
  where indexSub :: Int -> String
        indexSub n
          | n == 0    = []
          | otherwise = indexSub(n `div` 10) ++ [ toEnum (n `mod` 10 + fromEnum '₀') ]


data SemiSimple = DirectSum [Simple]

instance Eq SemiSimple where
  (==) (DirectSum xs) (DirectSum ys) = sortBy compareSimple xs == sortBy compareSimple ys

compareSimple :: Simple -> Simple -> Ordering
compareSimple x y
  | x == y        = EQ
  | smallerEq x y = LT
  | otherwise     = GT

smallerEq :: Simple -> Simple -> Bool
smallerEq (A n) (A m) = n <= m
smallerEq (B n) (B m) = n <= m
smallerEq (C n) (C m) = n <= m
smallerEq (D n) (D m) = n <= m
smallerEq x     y     = (toInt) x <= (toInt y)
  where toInt :: Simple -> Int
        toInt (A _) = 1
        toInt (B _) = 2
        toInt (C _) = 3
        toInt (D _) = 4
        toInt  E6   = 5
        toInt  E7   = 6
        toInt  E8   = 7
        toInt  F4   = 8
        toInt  G2   = 9

instance Show SemiSimple where
  show (DirectSum (x:xs))
    | null xs   = show x
    | otherwise = show x ++ " ⊕ " ++ show (DirectSum xs)