{-# LANGUAGE LambdaCase #-}
module Knots.Torus where

import Knots.PD

-- | Positive T(m,n) torus link
torusLink :: Int -> Int -> PD (Either Int Int)
torusLink m n = close m n $ concatMap (\i -> (map . fmap) (shift i) (turn m)) [0 .. (n-1)]
    where shift i (Left x)  = Left (x + i*m)
          shift i (Right x) = Right (x + i*m)

-- | Positive turn as a braid. Pass a negative argument to get a negative turn.
turn :: Int -> PD (Either Int Int)
turn m | m < 0  = mirror (turn (- m))
turn m | m == 1 = []
turn m | m == 2 = [ N (Left 1) (Left 3) (Left 2) (Left 0) ]
turn m | m >= 3 =      [ N (Left $ 1) (Right $ 0) (Left $ m+0) (Left $ 0) ]
                    ++ [ N (Left $ x+2) (Right $ x+1) (Left $ m+x+1) (Right $ x+0) | x <- [0..m-4] ]
                    ++ [ N (Left $ m-1) (Left $ 2*m-1) (Left $ 2*m-2) (Right $ m-3) ]

-- | @close m k@ closes the braid after @k@ many @m@-'turn's.
close m k = (map . fmap) (\case (Left i) -> if (i-m*k) >= 0 then Left (i-m*k) else Left i
                                other    -> other)