{-# OPTIONS_GHC -threaded #-}
module DobutokO.Sound.Functional.Split (
  
  splitO
  , splitO2
  , overConcat
  
  , splitHelp1
  , splitHelp2
  , splitOG1
  , splitOG2
  , splitOG12
  , splitOG12S
  , splitOG22
  , splitOG22S
) where
import CaseBi (getBFst')
import Data.Char (isAsciiLower)
import Data.List (sortBy)
import qualified Data.Vector as V
import DobutokO.Sound.Functional.Basics
splitO :: Int -> OvertonesO -> V.Vector OvertonesO
splitO n v0
 | compare (V.length v0) (n + 1) == GT =
    let v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0
        (x0, y0) = V.unsafeIndex v1 0
        v2 = V.unsafeSlice 1 (n - 1) v1
        v31 = V.map (\t -> (fst t) / x0) v2
        v32 = V.map (\t -> (snd t) / y0) v2
        v3 = V.zip v31 v32
        f1Tup (t1, w2) = V.imap (\ i _ -> (fst (V.unsafeIndex v3 i) * t1, snd (V.unsafeIndex v3 i) * w2)) v3
          in V.map f1Tup (V.unsafeSlice 0 n v1)
 | otherwise = V.singleton v0
splitO2 :: (OvertonesO -> OvertonesO) -> Int -> OvertonesO -> V.Vector OvertonesO
splitO2 h n v0
 | compare (V.length v0) (n + 1) == GT =
    let v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0
        (x0, y0) = V.unsafeIndex v1 0
        v2 = V.unsafeSlice 1 (n - 1) v1
        v31 = V.map (\t -> (fst t) / x0) v2
        v32 = V.map (\t -> (snd t) / y0) v2
        v3 = V.zip v31 v32
        f1Tup (t1, w2) = V.imap (\ i _ -> (fst (V.unsafeIndex v3 i) * t1, snd (V.unsafeIndex v3 i) * w2)) v3
          in V.map f1Tup (h . V.unsafeSlice 0 n $ v1)
 | otherwise = V.singleton v0
splitOG1 :: String -> Int -> OvertonesO -> V.Vector OvertonesO
splitOG1 xs n v0
 | compare (V.length v0) (n + 1) == GT =
    let c1s = take 2 . filter isAsciiLower $ xs
        v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0
        (x0, y0) = V.unsafeIndex v1 0 in
          case c1s of
            "ab" -> let (k1,k2,k3,k4) = (n - 1,V.length v0 - n,n - 1,V.length v0 - n) in splitHelp1 k1 k2 k3 k4 v1 (x0,y0)
            "ac" -> let (k1,k2,k3,k4) = (1,n - 1,n - 1,V.length v0 - n) in splitHelp1 k1 k2 k3 k4 v1 (x0,y0)
            "ad" -> let (k1,k2,k3,k4) = (n - 1,V.length v0 - n,0,n) in splitHelp1 k1 k2 k3 k4 v1 (x0,y0)
            _    -> let (k1,k2,k3,k4) = (1,n - 1,0,n) in splitHelp1 k1 k2 k3 k4 v1 (x0,y0)
 | otherwise = V.singleton v0
splitHelp1 :: Int -> Int -> Int -> Int -> OvertonesO -> (Float,Float) -> V.Vector OvertonesO
splitHelp1 x1 x2 x3 x4 v00 (y5,y6) =
  let v2 = V.unsafeSlice x1 x2 v00
      v31 = V.map (\t -> (fst t) / y5) v2
      v32 = V.map (\t -> (snd t) / y6) v2
      v3 = V.zip v31 v32
      f1Tup (t1, w2) = V.imap (\ i _ -> (fst (V.unsafeIndex v3 i) * t1, snd (V.unsafeIndex v3 i) * w2)) v3
        in V.map f1Tup (V.unsafeSlice x3 x4 v00)
splitHelp2 :: (OvertonesO -> OvertonesO) -> Int -> Int -> Int -> Int -> OvertonesO -> (Float,Float) -> V.Vector OvertonesO
splitHelp2 h1 x1 x2 x3 x4 v00 (y5,y6) =
  let v2 = V.unsafeSlice x1 x2 v00
      v31 = V.map (\t -> (fst t) / y5) v2
      v32 = V.map (\t -> (snd t) / y6) v2
      v3 = V.zip v31 v32
      f1Tup (t1, w2) = V.imap (\ i _ -> (fst (V.unsafeIndex v3 i) * t1, snd (V.unsafeIndex v3 i) * w2)) v3
        in V.map f1Tup (h1 . V.unsafeSlice x3 x4 $ v00)
splitOG2 :: (OvertonesO -> OvertonesO) -> String -> Int -> OvertonesO -> V.Vector OvertonesO
splitOG2 h xs n v0
 | compare (V.length v0) (n + 1) == GT =
    let c1s = take 2 . filter isAsciiLower $ xs
        v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0
        (x0, y0) = V.unsafeIndex v1 0 in
          case c1s of
            "ab" -> let (k1,k2,k3,k4) = (n - 1,V.length v0 - n,n - 1,V.length v0 - n) in splitHelp2 h k1 k2 k3 k4 v1 (x0,y0)
            "ac" -> let (k1,k2,k3,k4) = (1,n - 1,n - 1,V.length v0 - n) in splitHelp2 h k1 k2 k3 k4 v1 (x0,y0)
            "ad" -> let (k1,k2,k3,k4) = (n - 1,V.length v0 - n,0,n) in splitHelp2 h k1 k2 k3 k4 v1 (x0,y0)
            _    -> let (k1,k2,k3,k4) = (1,n - 1,0,n) in splitHelp2 h k1 k2 k3 k4 v1 (x0,y0)
 | otherwise = V.singleton v0
splitOG12 :: (Int,Int,Int,Int) -> V.Vector (String,Int -> OvertonesO -> (Int,Int,Int,Int)) -> String -> Int -> OvertonesO -> V.Vector OvertonesO
splitOG12 (x1,x2,x3,x4) vf xs n v0
 | compare (V.length v0) (n + 1) == GT && not (V.null vf) =
    let c1s = filter isAsciiLower $ xs
        v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0
        (x0, y0) = V.unsafeIndex v1 0 in let (k1,k2,k3,k4) = getBFst' ((x1,x2,x3,x4),V.map (\(ys,g) -> (ys,g n v1)) vf) c1s in
          splitHelp1 k1 k2 k3 k4 v1 (x0,y0)
 | otherwise = V.singleton v0
splitOG12S :: (Int,Int,Int,Int) -> V.Vector (String,Int -> OvertonesO -> (Int,Int,Int,Int)) -> String -> Int -> OvertonesO -> V.Vector OvertonesO
splitOG12S (x1,x2,x3,x4) vf xs n v0
 | compare (V.length v0) (n + 1) == GT && not (V.null vf) =
    let c1s = filter isAsciiLower $ xs
        v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0
        v2 = V.fromList . sortBy (\(x1s,_) (x2s,_) -> compare x1s x2s) . V.toList $ vf
        (x0, y0) = V.unsafeIndex v1 0 in let (k1,k2,k3,k4) = getBFst' ((x1,x2,x3,x4),V.map (\(ys,g) -> (ys,g n v1)) v2) c1s in
          splitHelp1 k1 k2 k3 k4 v1 (x0,y0)
 | otherwise = V.singleton v0
splitOG22 :: (Int,Int,Int,Int) -> V.Vector (String,Int -> OvertonesO -> (Int,Int,Int,Int)) -> (OvertonesO -> OvertonesO) -> String -> Int ->
  OvertonesO -> V.Vector OvertonesO
splitOG22 (x1,x2,x3,x4) vf h xs n v0
 | compare (V.length v0) (n + 1) == GT && not (V.null vf) =
    let c1s = filter isAsciiLower $ xs
        v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0
        (x0, y0) = V.unsafeIndex v1 0 in let (k1,k2,k3,k4) = getBFst' ((x1,x2,x3,x4),V.map (\(ys,g) -> (ys,g n v1)) vf) c1s in
          splitHelp2 h k1 k2 k3 k4 v1 (x0,y0)
 | otherwise = V.singleton v0
splitOG22S :: (Int,Int,Int,Int) -> V.Vector (String,Int -> OvertonesO -> (Int,Int,Int,Int)) -> (OvertonesO -> OvertonesO) -> String -> Int ->
  OvertonesO -> V.Vector OvertonesO
splitOG22S (x1,x2,x3,x4) vf h xs n v0
 | compare (V.length v0) (n + 1) == GT && not (V.null vf) =
    let c1s = filter isAsciiLower $ xs
        v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0
        v2 = V.fromList . sortBy (\(x1s,_) (x2s,_) -> compare x1s x2s) . V.toList $ vf
        (x0, y0) = V.unsafeIndex v1 0 in let (k1,k2,k3,k4) = getBFst' ((x1,x2,x3,x4),V.map (\(ys,g) -> (ys,g n v1)) v2) c1s in
          splitHelp2 h k1 k2 k3 k4 v1 (x0,y0)
 | otherwise = V.singleton v0
overConcat :: V.Vector OvertonesO -> OvertonesO
overConcat = V.concat . V.toList