module Bio.Protein.Metric
    ( Metricable (..)
    ) where

import           Data.Kind                      ( Type )
import           Data.Monoid                    ( First (..) )
import           Control.Lens
import           Bio.Utils.Geometry             ( V3R
                                                , R
                                                )
import qualified Bio.Utils.Geometry            as G

class Metricable m where
    type ReturnMetric m :: Type
    distance :: Getting m a V3R -> Getting m a V3R -> Getting (ReturnMetric m) a R
    angle    :: Getting m a V3R -> Getting m a V3R -> Getting m a V3R -> Getting (ReturnMetric m) a R
    dihedral :: Getting m a V3R -> Getting m a V3R -> Getting m a V3R -> Getting m a V3R -> Getting (ReturnMetric m) a R

instance Metricable (First V3R) where
    type ReturnMetric (First V3R) = First R
    distance :: Getting (First V3R) a V3R
-> Getting (First V3R) a V3R
-> Getting (ReturnMetric (First V3R)) a R
distance Getting (First V3R) a V3R
x Getting (First V3R) a V3R
y     R -> Const (ReturnMetric (First V3R)) R
_ a
aa = First R -> Const (First R) a
forall k a (b :: k). a -> Const a b
Const (First R -> Const (First R) a)
-> (Maybe R -> First R) -> Maybe R -> Const (First R) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe R -> First R
forall a. Maybe a -> First a
First (Maybe R -> Const (First R) a) -> Maybe R -> Const (First R) a
forall a b. (a -> b) -> a -> b
$ V3R -> V3R -> R
forall (f :: * -> *) a. (Metric f, Floating a) => f a -> f a -> a
G.distance (V3R -> V3R -> R) -> Maybe V3R -> Maybe (V3R -> R)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (a
aa a -> Getting (First V3R) a V3R -> Maybe V3R
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting (First V3R) a V3R
x) Maybe (V3R -> R) -> Maybe V3R -> Maybe R
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (a
aa a -> Getting (First V3R) a V3R -> Maybe V3R
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting (First V3R) a V3R
y)
    angle :: Getting (First V3R) a V3R
-> Getting (First V3R) a V3R
-> Getting (First V3R) a V3R
-> Getting (ReturnMetric (First V3R)) a R
angle    Getting (First V3R) a V3R
x Getting (First V3R) a V3R
y Getting (First V3R) a V3R
z   R -> Const (ReturnMetric (First V3R)) R
_ a
aa = First R -> Const (First R) a
forall k a (b :: k). a -> Const a b
Const (First R -> Const (First R) a)
-> (Maybe R -> First R) -> Maybe R -> Const (First R) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe R -> First R
forall a. Maybe a -> First a
First (Maybe R -> Const (First R) a) -> Maybe R -> Const (First R) a
forall a b. (a -> b) -> a -> b
$ V3R -> V3R -> R
G.angle (V3R -> V3R -> R) -> Maybe V3R -> Maybe (V3R -> R)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((-) (V3R -> V3R -> V3R) -> Maybe V3R -> Maybe (V3R -> V3R)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a
aa a -> Getting (First V3R) a V3R -> Maybe V3R
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting (First V3R) a V3R
x Maybe (V3R -> V3R) -> Maybe V3R -> Maybe V3R
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> a
aa a -> Getting (First V3R) a V3R -> Maybe V3R
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting (First V3R) a V3R
y) Maybe (V3R -> R) -> Maybe V3R -> Maybe R
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ((-) (V3R -> V3R -> V3R) -> Maybe V3R -> Maybe (V3R -> V3R)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a
aa a -> Getting (First V3R) a V3R -> Maybe V3R
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting (First V3R) a V3R
z Maybe (V3R -> V3R) -> Maybe V3R -> Maybe V3R
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> a
aa a -> Getting (First V3R) a V3R -> Maybe V3R
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting (First V3R) a V3R
y)
    dihedral :: Getting (First V3R) a V3R
-> Getting (First V3R) a V3R
-> Getting (First V3R) a V3R
-> Getting (First V3R) a V3R
-> Getting (ReturnMetric (First V3R)) a R
dihedral Getting (First V3R) a V3R
x Getting (First V3R) a V3R
y Getting (First V3R) a V3R
z Getting (First V3R) a V3R
w R -> Const (ReturnMetric (First V3R)) R
_ a
aa = First R -> Const (First R) a
forall k a (b :: k). a -> Const a b
Const (First R -> Const (First R) a)
-> (Maybe R -> First R) -> Maybe R -> Const (First R) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe R -> First R
forall a. Maybe a -> First a
First (Maybe R -> Const (First R) a) -> Maybe R -> Const (First R) a
forall a b. (a -> b) -> a -> b
$ V3R -> V3R -> V3R -> V3R -> R
G.dihedral (V3R -> V3R -> V3R -> V3R -> R)
-> Maybe V3R -> Maybe (V3R -> V3R -> V3R -> R)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (a
aa a -> Getting (First V3R) a V3R -> Maybe V3R
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting (First V3R) a V3R
x) Maybe (V3R -> V3R -> V3R -> R)
-> Maybe V3R -> Maybe (V3R -> V3R -> R)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (a
aa a -> Getting (First V3R) a V3R -> Maybe V3R
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting (First V3R) a V3R
y) Maybe (V3R -> V3R -> R) -> Maybe V3R -> Maybe (V3R -> R)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (a
aa a -> Getting (First V3R) a V3R -> Maybe V3R
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting (First V3R) a V3R
z) Maybe (V3R -> R) -> Maybe V3R -> Maybe R
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (a
aa a -> Getting (First V3R) a V3R -> Maybe V3R
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting (First V3R) a V3R
w)

instance Metricable V3R where
    type ReturnMetric V3R = R
    distance :: Getting V3R a V3R
-> Getting V3R a V3R -> Getting (ReturnMetric V3R) a R
distance Getting V3R a V3R
x Getting V3R a V3R
y R -> Const (ReturnMetric V3R) R
_ a
aa = R -> Const R a
forall k a (b :: k). a -> Const a b
Const (R -> Const R a) -> R -> Const R a
forall a b. (a -> b) -> a -> b
$ V3R -> V3R -> R
forall (f :: * -> *) a. (Metric f, Floating a) => f a -> f a -> a
G.distance (a
aa a -> Getting V3R a V3R -> V3R
forall s a. s -> Getting a s a -> a
^. Getting V3R a V3R
x) (a
aa a -> Getting V3R a V3R -> V3R
forall s a. s -> Getting a s a -> a
^. Getting V3R a V3R
y)
    angle :: Getting V3R a V3R
-> Getting V3R a V3R
-> Getting V3R a V3R
-> Getting (ReturnMetric V3R) a R
angle Getting V3R a V3R
x Getting V3R a V3R
y Getting V3R a V3R
z R -> Const (ReturnMetric V3R) R
_ a
aa = R -> Const R a
forall k a (b :: k). a -> Const a b
Const (R -> Const R a) -> R -> Const R a
forall a b. (a -> b) -> a -> b
$ V3R -> V3R -> R
G.angle (a
aa a -> Getting V3R a V3R -> V3R
forall s a. s -> Getting a s a -> a
^. Getting V3R a V3R
x V3R -> V3R -> V3R
forall a. Num a => a -> a -> a
- a
aa a -> Getting V3R a V3R -> V3R
forall s a. s -> Getting a s a -> a
^. Getting V3R a V3R
y) (a
aa a -> Getting V3R a V3R -> V3R
forall s a. s -> Getting a s a -> a
^. Getting V3R a V3R
z V3R -> V3R -> V3R
forall a. Num a => a -> a -> a
- a
aa a -> Getting V3R a V3R -> V3R
forall s a. s -> Getting a s a -> a
^. Getting V3R a V3R
y)
    dihedral :: Getting V3R a V3R
-> Getting V3R a V3R
-> Getting V3R a V3R
-> Getting V3R a V3R
-> Getting (ReturnMetric V3R) a R
dihedral Getting V3R a V3R
x Getting V3R a V3R
y Getting V3R a V3R
z Getting V3R a V3R
w R -> Const (ReturnMetric V3R) R
_ a
aa = R -> Const R a
forall k a (b :: k). a -> Const a b
Const (R -> Const R a) -> R -> Const R a
forall a b. (a -> b) -> a -> b
$ V3R -> V3R -> V3R -> V3R -> R
G.dihedral (a
aa a -> Getting V3R a V3R -> V3R
forall s a. s -> Getting a s a -> a
^. Getting V3R a V3R
x) (a
aa a -> Getting V3R a V3R -> V3R
forall s a. s -> Getting a s a -> a
^. Getting V3R a V3R
y) (a
aa a -> Getting V3R a V3R -> V3R
forall s a. s -> Getting a s a -> a
^. Getting V3R a V3R
z) (a
aa a -> Getting V3R a V3R -> V3R
forall s a. s -> Getting a s a -> a
^. Getting V3R a V3R
w)