module Language.Mecha.Assembly
  ( Asm
  , place
  , assemble
  , view
  ) where

import qualified Graphics.Rendering.OpenGL as GL

import Language.Mecha.Mesh
import Language.Mecha.OpenGL
import Language.Mecha.Solid
import Language.Mecha.Types
import Language.Mecha.Viewer

-- | The Asm holds all the parts and sub-assemblies.
newtype Asm = Asm (IO ())

instance Colorable Asm where
  color (r,g,b) (Asm a) = Asm $ color3 r g b >> a

transform :: IO () -> Asm -> Asm
transform action (Asm a) = Asm $ GL.preservingMatrix (action >> a)

instance Moveable Asm where
  move (x, y, z) = transform (translate3 x y z)
  rotate (x, y, z) angle = transform (rotate3 angle x y z)

-- | Place a part (Solid) in an assembly.
place :: Double -> Double -> Int -> Solid -> Asm
place r p n a = Asm $ GL.renderPrimitive GL.Triangles $ sequence_ [ normal3 nx ny nz >> vertex3 vx vy vz | ((nx, ny, nz), (vx, vy, vz)) <- mesh r p n a ]

-- | Assemble multiple sub-assemblies together.
assemble :: [Asm] -> Asm
assemble a = Asm $ sequence_ [ a | Asm a <- a ]

-- | View an assembly given radius, precision, and vertex refinement level.
view :: Asm -> IO ()
view (Asm a) = viewer a